Pārlūkot izejas kodu

Merge pull request #2001 from CraigFeldspar/master

Uniform Buffer Objects
David Catuhe 8 gadi atpakaļ
vecāks
revīzija
8ff323c7fe
91 mainītis faili ar 11690 papildinājumiem un 5431 dzēšanām
  1. 1 2
      Playground/index-local.html
  2. 9 0
      Tools/Gulp/config.json
  3. 31 0
      dist/preview release/babylon.core.js
  4. 3395 2109
      dist/preview release/babylon.d.ts
  5. 41 41
      dist/preview release/babylon.js
  6. 1043 215
      dist/preview release/babylon.max.js
  7. 3395 2109
      dist/preview release/babylon.module.d.ts
  8. 41 0
      dist/preview release/babylon.noworker.js
  9. 41 41
      dist/preview release/babylon.worker.js
  10. 11 11
      dist/preview release/canvas2D/babylon.canvas2d.min.js
  11. 249 249
      dist/preview release/inspector/babylon.inspector.bundle.js
  12. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  13. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  14. 1 1
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  15. 2 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  16. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  17. 20 11
      dist/preview release/materialsLibrary/babylon.fireMaterial.js
  18. 1 1
      dist/preview release/materialsLibrary/babylon.fireMaterial.min.js
  19. 20 3
      dist/preview release/materialsLibrary/babylon.furMaterial.js
  20. 1 1
      dist/preview release/materialsLibrary/babylon.furMaterial.min.js
  21. 24 10
      dist/preview release/materialsLibrary/babylon.gradientMaterial.js
  22. 1 1
      dist/preview release/materialsLibrary/babylon.gradientMaterial.min.js
  23. 26 10
      dist/preview release/materialsLibrary/babylon.lavaMaterial.js
  24. 1 1
      dist/preview release/materialsLibrary/babylon.lavaMaterial.min.js
  25. 24 10
      dist/preview release/materialsLibrary/babylon.normalMaterial.js
  26. 1 1
      dist/preview release/materialsLibrary/babylon.normalMaterial.min.js
  27. 20 3
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.js
  28. 1 1
      dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js
  29. 20 3
      dist/preview release/materialsLibrary/babylon.simpleMaterial.js
  30. 1 1
      dist/preview release/materialsLibrary/babylon.simpleMaterial.min.js
  31. 20 3
      dist/preview release/materialsLibrary/babylon.terrainMaterial.js
  32. 1 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.min.js
  33. 20 3
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.js
  34. 1 1
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.min.js
  35. 20 3
      dist/preview release/materialsLibrary/babylon.waterMaterial.js
  36. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  37. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  38. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  39. 20 14
      materialsLibrary/src/fire/babylon.fireMaterial.ts
  40. 20 3
      materialsLibrary/src/fur/babylon.furMaterial.ts
  41. 1 1
      materialsLibrary/src/fur/fur.fragment.fx
  42. 30 16
      materialsLibrary/src/gradient/babylon.gradientMaterial.ts
  43. 4 4
      materialsLibrary/src/gradient/gradient.fragment.fx
  44. 35 18
      materialsLibrary/src/lava/babylon.lavaMaterial.ts
  45. 4 4
      materialsLibrary/src/lava/lava.fragment.fx
  46. 30 16
      materialsLibrary/src/normal/babylon.normalMaterial.ts
  47. 4 4
      materialsLibrary/src/normal/normal.fragment.fx
  48. 21 4
      materialsLibrary/src/shadowOnly/babylon.shadowOnlyMaterial.ts
  49. 1 1
      materialsLibrary/src/shadowOnly/shadowOnly.fragment.fx
  50. 21 5
      materialsLibrary/src/simple/babylon.simpleMaterial.ts
  51. 1 1
      materialsLibrary/src/simple/simple.fragment.fx
  52. 21 5
      materialsLibrary/src/terrain/babylon.terrainMaterial.ts
  53. 1 1
      materialsLibrary/src/terrain/terrain.fragment.fx
  54. 21 4
      materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts
  55. 1 1
      materialsLibrary/src/triPlanar/triplanar.fragment.fx
  56. 21 5
      materialsLibrary/src/water/babylon.waterMaterial.ts
  57. 1 1
      materialsLibrary/src/water/water.fragment.fx
  58. 12 3
      src/Lights/babylon.directionalLight.ts
  59. 15 4
      src/Lights/babylon.hemisphericLight.ts
  60. 13 1
      src/Lights/babylon.light.ts
  61. 15 4
      src/Lights/babylon.pointLight.ts
  62. 20 7
      src/Lights/babylon.spotLight.ts
  63. 53 2
      src/Materials/babylon.effect.ts
  64. 27 0
      src/Materials/babylon.material.ts
  65. 27 20
      src/Materials/babylon.materialHelper.ts
  66. 290 169
      src/Materials/babylon.pbrMaterial.ts
  67. 0 1
      src/Materials/babylon.pushMaterial.ts
  68. 11 5
      src/Materials/babylon.shaderMaterial.ts
  69. 149 71
      src/Materials/babylon.standardMaterial.ts
  70. 611 0
      src/Materials/babylon.uniformBuffer.ts
  71. 2 2
      src/Math/babylon.math.ts
  72. 0 1
      src/Shaders/ShadersInclude/bumpFragmentFunctions.fx
  73. 84 0
      src/Shaders/ShadersInclude/defaultFragmentDeclaration.fx
  74. 41 0
      src/Shaders/ShadersInclude/defaultUboDeclaration.fx
  75. 42 0
      src/Shaders/ShadersInclude/defaultVertexDeclaration.fx
  76. 9 12
      src/Shaders/ShadersInclude/lightFragment.fx
  77. 2 0
      src/Shaders/ShadersInclude/lightFragmentDeclaration.fx
  78. 25 0
      src/Shaders/ShadersInclude/lightUboDeclaration.fx
  79. 92 0
      src/Shaders/ShadersInclude/pbrFragmentDeclaration.fx
  80. 9 12
      src/Shaders/ShadersInclude/pbrLightFunctionsCall.fx
  81. 52 0
      src/Shaders/ShadersInclude/pbrUboDeclaration.fx
  82. 46 0
      src/Shaders/ShadersInclude/pbrVertexDeclaration.fx
  83. 1 1
      src/Shaders/ShadersInclude/pointCloudVertexDeclaration.fx
  84. 4 48
      src/Shaders/default.fragment.fx
  85. 3 20
      src/Shaders/default.vertex.fx
  86. 4 54
      src/Shaders/pbr.fragment.fx
  87. 2 24
      src/Shaders/pbr.vertex.fx
  88. 73 1
      src/babylon.engine.ts
  89. 6 4
      src/babylon.mixins.ts
  90. 24 0
      src/babylon.scene.ts
  91. 1176 0
      src/babylon.webgl2.ts

+ 1 - 2
Playground/index-local.html

@@ -149,9 +149,8 @@
     <script src="https://code.jquery.com/jquery.js"></script>
 
     <script src="js/actions.js"></script>
-    <script src="js/index.js"></script>
     <script>
-        BABYLONDEVTOOLS.Loader.require('index.js')
+        BABYLONDEVTOOLS.Loader.require('js/index.js')
             .load();
     </script>
 </body>

+ 9 - 0
Tools/Gulp/config.json

@@ -57,6 +57,7 @@
                 "../../src/Materials/babylon.effect.js",
                 "../../src/Materials/babylon.materialHelper.js",
                 "../../src/Materials/babylon.material.js",
+                "../../src/Materials/babylon.uniformBuffer.js",
                 "../../src/Materials/babylon.pushMaterial.js",
                 "../../src/Mesh/babylon.mesh.vertexData.js",
                 "../../src/Mesh/babylon.geometry.js",
@@ -214,6 +215,10 @@
                 "helperFunctions",
                 "lightFragmentDeclaration",
                 "lightsFragmentFunctions",
+                "lightUboDeclaration",
+                "defaultVertexDeclaration",
+                "defaultFragmentDeclaration",
+                "defaultUboDeclaration",
                 "shadowsFragmentFunctions",
                 "fresnelFunction",
                 "reflectionFunction",
@@ -263,6 +268,10 @@
                 "shadowsVertex",
                 "logDepthVertex",
                 "lightFragmentDeclaration",
+                "lightUboDeclaration",
+                "pbrVertexDeclaration",
+                "pbrFragmentDeclaration",
+                "pbrUboDeclaration",
                 "fresnelFunction",
                 "reflectionFunction",                
                 "colorGradingDefinition",

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 31 - 0
dist/preview release/babylon.core.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 3395 - 2109
dist/preview release/babylon.d.ts


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 41 - 41
dist/preview release/babylon.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1043 - 215
dist/preview release/babylon.max.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 3395 - 2109
dist/preview release/babylon.module.d.ts


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 41 - 0
dist/preview release/babylon.noworker.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 41 - 41
dist/preview release/babylon.worker.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 11 - 11
dist/preview release/canvas2D/babylon.canvas2d.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 249 - 249
dist/preview release/inspector/babylon.inspector.bundle.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 2 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 20 - 11
dist/preview release/materialsLibrary/babylon.fireMaterial.js

@@ -121,17 +121,26 @@ var BABYLON;
                 // Legacy browser patch
                 var shaderName = "fire";
                 var join = defines.toString();
-                subMesh.setEffect(scene.getEngine().createEffect(shaderName, attribs, ["world", "view", "viewProjection", "vEyePosition",
-                    "vFogInfos", "vFogColor", "pointSize",
-                    "vDiffuseInfos",
-                    "mBones",
-                    "vClipPlane", "diffuseMatrix",
-                    // Fire
-                    "time", "speed"
-                ], ["diffuseSampler",
-                    // Fire
-                    "distortionSampler", "opacitySampler"
-                ], join, fallbacks, this.onCompiled, this.onError), defines);
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, {
+                    attributes: attribs,
+                    uniformsNames: ["world", "view", "viewProjection", "vEyePosition",
+                        "vFogInfos", "vFogColor", "pointSize",
+                        "vDiffuseInfos",
+                        "mBones",
+                        "vClipPlane", "diffuseMatrix",
+                        // Fire
+                        "time", "speed"
+                    ],
+                    uniformBuffersNames: [],
+                    samplers: ["diffuseSampler",
+                        // Fire
+                        "distortionSampler", "opacitySampler"
+                    ],
+                    defines: join,
+                    fallbacks: fallbacks,
+                    onCompiled: this.onCompiled,
+                    onError: this.onError
+                }, engine), defines);
             }
             if (!subMesh.effect.isReady()) {
                 return false;

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.fireMaterial.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 20 - 3
dist/preview release/materialsLibrary/babylon.furMaterial.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.furMaterial.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 24 - 10
dist/preview release/materialsLibrary/babylon.gradientMaterial.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.gradientMaterial.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 26 - 10
dist/preview release/materialsLibrary/babylon.lavaMaterial.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.lavaMaterial.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 24 - 10
dist/preview release/materialsLibrary/babylon.normalMaterial.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.normalMaterial.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 20 - 3
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.shadowOnlyMaterial.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 20 - 3
dist/preview release/materialsLibrary/babylon.simpleMaterial.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.simpleMaterial.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 20 - 3
dist/preview release/materialsLibrary/babylon.terrainMaterial.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.terrainMaterial.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 20 - 3
dist/preview release/materialsLibrary/babylon.triPlanarMaterial.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.triPlanarMaterial.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 20 - 3
dist/preview release/materialsLibrary/babylon.waterMaterial.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


+ 20 - 14
materialsLibrary/src/fire/babylon.fireMaterial.ts

@@ -146,20 +146,26 @@ module BABYLON {
                 
                 var join = defines.toString();
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
-                    attribs,
-                    ["world", "view", "viewProjection", "vEyePosition",
-                        "vFogInfos", "vFogColor", "pointSize",
-                        "vDiffuseInfos", 
-                        "mBones",
-                        "vClipPlane", "diffuseMatrix",
-                        // Fire
-                        "time", "speed"
-                    ],
-                    ["diffuseSampler",
-                        // Fire
-                        "distortionSampler", "opacitySampler"
-                    ],
-                    join, fallbacks, this.onCompiled, this.onError), defines);
+                    <EffectCreationOptions>{
+                        attributes: attribs,
+                        uniformsNames: ["world", "view", "viewProjection", "vEyePosition",
+                                "vFogInfos", "vFogColor", "pointSize",
+                                "vDiffuseInfos", 
+                                "mBones",
+                                "vClipPlane", "diffuseMatrix",
+                                // Fire
+                                "time", "speed"
+                            ],
+                        uniformBuffersNames: [],
+                        samplers: ["diffuseSampler",
+                                // Fire
+                                "distortionSampler", "opacitySampler"
+                            ],
+                        defines: join,
+                        fallbacks: fallbacks,
+                        onCompiled: this.onCompiled,
+                        onError: this.onError
+                    }, engine), defines);
             }
             
             if (!subMesh.effect.isReady()) {

+ 20 - 3
materialsLibrary/src/fur/babylon.furMaterial.ts

@@ -246,11 +246,28 @@ module BABYLON {
                     "heightTexture", "furTexture"
                 ];
                 
-                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, this.maxSimultaneousLights);
+                var uniformBuffers = [];
+
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: defines, 
+                    maxSimultaneousLights: this.maxSimultaneousLights
+                });
                 
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
-                    attribs, uniforms, samplers,
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights }), defines);
+                    <EffectCreationOptions>{
+                        attributes: attribs,
+                        uniformsNames: uniforms,
+                        uniformBuffersNames: uniformBuffers,
+                        samplers: samplers,
+                        defines: join,
+                        fallbacks: fallbacks,
+                        onCompiled: this.onCompiled,
+                        onError: this.onError,
+                        indexParameters: { maxSimultaneousLights: this.maxSimultaneousLights }
+                    }, engine), defines);
             }
             if (!subMesh.effect.isReady()) {
                 return false;

+ 1 - 1
materialsLibrary/src/fur/fur.fragment.fx

@@ -19,7 +19,7 @@ varying vec4 vColor;
 #endif
 
 // Lights
-#include<lightFragmentDeclaration>[0..maxSimultaneousLights]
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
 
 // Samplers
 #ifdef DIFFUSE

+ 30 - 16
materialsLibrary/src/gradient/babylon.gradientMaterial.ts

@@ -182,23 +182,37 @@ module BABYLON {
                 // Legacy browser patch
                 var shaderName = "gradient";
                 var join = defines.toString();
+
+                var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
+                    "vFogInfos", "vFogColor", "pointSize",
+                    "vDiffuseInfos", 
+                    "mBones",
+                    "vClipPlane", "diffuseMatrix",
+                    "depthValues", "topColor", "bottomColor", "offset", "smoothness"
+                ];
+                var samplers = ["diffuseSampler"];
+                var uniformBuffers = [];
+
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: defines, 
+                    maxSimultaneousLights: 4
+                });
+                
                 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",
-                        "vClipPlane", "diffuseMatrix",
-                        "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3", "depthValues", "topColor", "bottomColor", "offset", "smoothness"
-                    ],
-                    ["diffuseSampler",
-                        "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
-                    ],
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: 4 }), defines);
+                    <EffectCreationOptions>{
+                        attributes: attribs,
+                        uniformsNames: uniforms,
+                        uniformBuffersNames: uniformBuffers,
+                        samplers: samplers,
+                        defines: join,
+                        fallbacks: fallbacks,
+                        onCompiled: this.onCompiled,
+                        onError: this.onError,
+                        indexParameters: { maxSimultaneousLights: 4 }
+                    }, engine), defines);
             }
             if (!subMesh.effect.isReady()) {
                 return false;

+ 4 - 4
materialsLibrary/src/gradient/gradient.fragment.fx

@@ -23,10 +23,10 @@ varying vec4 vColor;
 
 // Lights
 
-#include<lightFragmentDeclaration>[0]
-#include<lightFragmentDeclaration>[1]
-#include<lightFragmentDeclaration>[2]
-#include<lightFragmentDeclaration>[3]
+#include<__decl__lightFragment>[0]
+#include<__decl__lightFragment>[1]
+#include<__decl__lightFragment>[2]
+#include<__decl__lightFragment>[3]
 
 
 #include<lightsFragmentFunctions>

+ 35 - 18
materialsLibrary/src/lava/babylon.lavaMaterial.ts

@@ -206,25 +206,42 @@ module BABYLON {
                 // Legacy browser patch
                 var shaderName = "lava";
                 var join = defines.toString();
+
+                var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
+                    "vFogInfos", "vFogColor", "pointSize",
+                    "vDiffuseInfos",
+                    "mBones",
+                    "vClipPlane", "diffuseMatrix",
+                    "depthValues",
+                    "time", "speed","movingSpeed",
+                    "fogColor","fogDensity", "lowFrequencySpeed"
+                ];
+
+                var samplers = ["diffuseSampler",
+                    "noiseTexture"
+                ];
+                var uniformBuffers = [];
+
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: defines, 
+                    maxSimultaneousLights: this.maxSimultaneousLights
+                });
+
                 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",
-                        "vClipPlane", "diffuseMatrix",
-                        "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3", "depthValues",
-                        "time", "speed","movingSpeed",
-                        "fogColor","fogDensity", "lowFrequencySpeed"
-                    ],
-                    ["diffuseSampler",
-                        "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3", "noiseTexture"
-                    ],
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights - 1 }), defines);
+                    <EffectCreationOptions>{
+                        attributes: attribs,
+                        uniformsNames: uniforms,
+                        uniformBuffersNames: uniformBuffers,
+                        samplers: samplers,
+                        defines: join,
+                        fallbacks: fallbacks,
+                        onCompiled: this.onCompiled,
+                        onError: this.onError,
+                        indexParameters: { maxSimultaneousLights: this.maxSimultaneousLights }
+                    }, engine), defines);
             }
             if (!subMesh.effect.isReady()) {
                 return false;

+ 4 - 4
materialsLibrary/src/lava/lava.fragment.fx

@@ -27,10 +27,10 @@ varying vec4 vColor;
 #endif
 
 // Lights
-#include<lightFragmentDeclaration>[0]
-#include<lightFragmentDeclaration>[1]
-#include<lightFragmentDeclaration>[2]
-#include<lightFragmentDeclaration>[3]
+#include<__decl__lightFragment>[0]
+#include<__decl__lightFragment>[1]
+#include<__decl__lightFragment>[2]
+#include<__decl__lightFragment>[3]
 
 
 #include<lightsFragmentFunctions>

+ 30 - 16
materialsLibrary/src/normal/babylon.normalMaterial.ts

@@ -186,23 +186,37 @@ module BABYLON {
 
                 var shaderName = "normal";
                 var join = defines.toString();
+
+                var uniforms = ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
+                    "vFogInfos", "vFogColor", "pointSize",
+                    "vDiffuseInfos", 
+                    "mBones",
+                    "vClipPlane", "diffuseMatrix",
+                    "depthValues"
+                ];
+                var samplers = ["diffuseSampler"];
+                var uniformBuffers = [];
+
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: defines, 
+                    maxSimultaneousLights: 4
+                });
+
                 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",
-                        "vClipPlane", "diffuseMatrix",
-                        "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3", "depthValues"
-                    ],
-                    ["diffuseSampler",
-                        "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
-                    ],
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: 4 }), defines);
+                    <EffectCreationOptions>{
+                        attributes: attribs,
+                        uniformsNames: uniforms,
+                        uniformBuffersNames: uniformBuffers,
+                        samplers: samplers,
+                        defines: join,
+                        fallbacks: fallbacks,
+                        onCompiled: this.onCompiled,
+                        onError: this.onError,
+                        indexParameters: { maxSimultaneousLights: 4 }
+                    }, engine), defines);
             }
             if (!subMesh.effect.isReady()) {
                 return false;

+ 4 - 4
materialsLibrary/src/normal/normal.fragment.fx

@@ -16,10 +16,10 @@ varying vec4 vColor;
 #endif
 
 // Lights
-#include<lightFragmentDeclaration>[0]
-#include<lightFragmentDeclaration>[1]
-#include<lightFragmentDeclaration>[2]
-#include<lightFragmentDeclaration>[3]
+#include<__decl__lightFragment>[0]
+#include<__decl__lightFragment>[1]
+#include<__decl__lightFragment>[2]
+#include<__decl__lightFragment>[3]
 
 
 #include<lightsFragmentFunctions>

+ 21 - 4
materialsLibrary/src/shadowOnly/babylon.shadowOnlyMaterial.ts

@@ -107,12 +107,29 @@ module BABYLON {
                                 "vClipPlane", "depthValues"
                 ];
                 var samplers = [];
-                    
-                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, 1);
+                
+                var uniformBuffers = [];
+
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: defines, 
+                    maxSimultaneousLights: 1
+                });
                 
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
-                    attribs, uniforms, samplers,
-                    join, fallbacks, this.onCompiled, this.onError, {maxSimultaneousLights: 1}), defines);
+                    <EffectCreationOptions>{
+                        attributes: attribs,
+                        uniformsNames: uniforms,
+                        uniformBuffersNames: uniformBuffers,
+                        samplers: samplers,
+                        defines: join,
+                        fallbacks: fallbacks,
+                        onCompiled: this.onCompiled,
+                        onError: this.onError,
+                        indexParameters: { maxSimultaneousLights: 1 }
+                    }, engine), defines);
             }
             if (!subMesh.effect.isReady()) {
                 return false;

+ 1 - 1
materialsLibrary/src/shadowOnly/shadowOnly.fragment.fx

@@ -11,7 +11,7 @@ varying vec3 vNormalW;
 #endif
 
 // Lights
-#include<lightFragmentDeclaration>[0..maxSimultaneousLights]
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
 
 #include<lightsFragmentFunctions>
 #include<shadowsFragmentFunctions>

+ 21 - 5
materialsLibrary/src/simple/babylon.simpleMaterial.ts

@@ -159,12 +159,28 @@ module BABYLON {
                                 "vClipPlane", "diffuseMatrix", "depthValues"
                 ];
                 var samplers = ["diffuseSampler"];
-                    
-                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, this.maxSimultaneousLights);
-                
+                var uniformBuffers = [];
+
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: defines, 
+                    maxSimultaneousLights: this.maxSimultaneousLights
+                });
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
-                    attribs, uniforms, samplers,
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this._maxSimultaneousLights - 1 }), defines);
+                    <EffectCreationOptions>{
+                        attributes: attribs,
+                        uniformsNames: uniforms,
+                        uniformBuffersNames: uniformBuffers,
+                        samplers: samplers,
+                        defines: join,
+                        fallbacks: fallbacks,
+                        onCompiled: this.onCompiled,
+                        onError: this.onError,
+                        indexParameters: { maxSimultaneousLights: this._maxSimultaneousLights - 1 }
+                    }, engine), defines);
+
             }
             if (!subMesh.effect.isReady()) {
                 return false;

+ 1 - 1
materialsLibrary/src/simple/simple.fragment.fx

@@ -16,7 +16,7 @@ varying vec4 vColor;
 #endif
 
 // Lights
-#include<lightFragmentDeclaration>[0..maxSimultaneousLights]
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
 
 
 #include<lightsFragmentFunctions>

+ 21 - 5
materialsLibrary/src/terrain/babylon.terrainMaterial.ts

@@ -198,18 +198,34 @@ module BABYLON {
                     "vTextureInfos", 
                     "mBones",
                     "vClipPlane", "textureMatrix",
-                    
                     "diffuse1Infos", "diffuse2Infos", "diffuse3Infos"
                 ];
                 var samplers = ["textureSampler", "diffuse1Sampler", "diffuse2Sampler", "diffuse3Sampler",
                     "bump1Sampler", "bump2Sampler", "bump3Sampler"
                 ];
-                
-                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, this.maxSimultaneousLights);
+
+                var uniformBuffers = [];
+
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: defines, 
+                    maxSimultaneousLights: this.maxSimultaneousLights
+                });
                 
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
-                    attribs, uniforms, samplers,
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights }), defines);
+                    <EffectCreationOptions>{
+                        attributes: attribs,
+                        uniformsNames: uniforms,
+                        uniformBuffersNames: uniformBuffers,
+                        samplers: samplers,
+                        defines: join,
+                        fallbacks: fallbacks,
+                        onCompiled: this.onCompiled,
+                        onError: this.onError,
+                        indexParameters: { maxSimultaneousLights: this.maxSimultaneousLights }
+                    }, engine), defines);
             }
             if (!subMesh.effect.isReady()) {
                 return false;

+ 1 - 1
materialsLibrary/src/terrain/terrain.fragment.fx

@@ -20,7 +20,7 @@ varying vec4 vColor;
 #endif
 
 // Lights
-#include<lightFragmentDeclaration>[0..maxSimultaneousLights]
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
 
 // Samplers
 #ifdef DIFFUSE

+ 21 - 4
materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts

@@ -215,12 +215,29 @@ module BABYLON {
                 var samplers = ["diffuseSamplerX", "diffuseSamplerY", "diffuseSamplerZ",
                     "normalSamplerX", "normalSamplerY", "normalSamplerZ"
                 ];
-                
-                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, this.maxSimultaneousLights);
+
+                var uniformBuffers = [];
+
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: defines, 
+                    maxSimultaneousLights: this.maxSimultaneousLights
+                });
                 
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
-                    attribs, uniforms, samplers,
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights }), defines);
+                    <EffectCreationOptions>{
+                        attributes: attribs,
+                        uniformsNames: uniforms,
+                        uniformBuffersNames: uniformBuffers,
+                        samplers: samplers,
+                        defines: join,
+                        fallbacks: fallbacks,
+                        onCompiled: this.onCompiled,
+                        onError: this.onError,
+                        indexParameters: { maxSimultaneousLights: this.maxSimultaneousLights }
+                    }, engine), defines);
             }
             if (!subMesh.effect.isReady()) {
                 return false;

+ 1 - 1
materialsLibrary/src/triPlanar/triplanar.fragment.fx

@@ -16,7 +16,7 @@ varying vec4 vColor;
 #endif
 
 // Lights
-#include<lightFragmentDeclaration>[0..maxSimultaneousLights]
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
 
 // Samplers
 #ifdef DIFFUSEX

+ 21 - 5
materialsLibrary/src/water/babylon.waterMaterial.ts

@@ -340,12 +340,28 @@ module BABYLON {
                     // Water
                     "refractionSampler", "reflectionSampler"
                 ];
-                
-                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, this.maxSimultaneousLights);
-                
+                var uniformBuffers = [];
+
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: defines, 
+                    maxSimultaneousLights: this.maxSimultaneousLights
+                });
                 subMesh.setEffect(scene.getEngine().createEffect(shaderName,
-                    attribs, uniforms, samplers,
-                    join, fallbacks, this.onCompiled, this.onError, { maxSimultaneousLights: this.maxSimultaneousLights }), defines);
+                    <EffectCreationOptions>{
+                        attributes: attribs,
+                        uniformsNames: uniforms,
+                        uniformBuffersNames: uniformBuffers,
+                        samplers: samplers,
+                        defines: join,
+                        fallbacks: fallbacks,
+                        onCompiled: this.onCompiled,
+                        onError: this.onError,
+                        indexParameters: { maxSimultaneousLights: this._maxSimultaneousLights }
+                    }, engine), defines);
+
             }
             if (!subMesh.effect.isReady()) {
                 return false;

+ 1 - 1
materialsLibrary/src/water/water.fragment.fx

@@ -24,7 +24,7 @@ varying vec4 vColor;
 #endif
 
 // Lights
-#include<lightFragmentDeclaration>[0..maxSimultaneousLights]
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
 
 #include<lightsFragmentFunctions>
 #include<shadowsFragmentFunctions>

+ 12 - 3
src/Lights/babylon.directionalLight.ts

@@ -42,6 +42,15 @@ module BABYLON {
             this.position = direction.scale(-1.0);
             this.direction = direction;
         }
+
+        protected _buildUniformLayout(): void {
+             this._uniformBuffer.addUniform("vLightData", 4);
+             this._uniformBuffer.addUniform("vLightDiffuse", 4);
+             this._uniformBuffer.addUniform("vLightSpecular", 3);
+             this._uniformBuffer.addUniform("shadowsInfo", 3);
+             this._uniformBuffer.create();
+        }
+
         /**
          * Returns the string "DirectionalLight".  
          */
@@ -165,16 +174,16 @@ module BABYLON {
          * Sets the passed Effect object with the DirectionalLight transformed position (or position if not parented) and the passed name.  
          * Returns the DirectionalLight.  
          */
-        public transferToEffect(effect: Effect, directionUniformName: string): DirectionalLight {
+        public transferToEffect(effect: Effect, lightIndex: string): DirectionalLight {
             if (this.parent && this.parent.getWorldMatrix) {
                 if (!this._transformedDirection) {
                     this._transformedDirection = Vector3.Zero();
                 }
                 Vector3.TransformNormalToRef(this.direction, this.parent.getWorldMatrix(), this._transformedDirection);
-                effect.setFloat4(directionUniformName, this._transformedDirection.x, this._transformedDirection.y, this._transformedDirection.z, 1);
+                this._uniformBuffer.updateFloat4("vLightData", this._transformedDirection.x, this._transformedDirection.y, this._transformedDirection.z, 1, lightIndex);
                 return this;
             }
-            effect.setFloat4(directionUniformName, this.direction.x, this.direction.y, this.direction.z, 1);
+            this._uniformBuffer.updateFloat4("vLightData", this.direction.x, this.direction.y, this.direction.z, 1, lightIndex);
             return this;
         }
 

+ 15 - 4
src/Lights/babylon.hemisphericLight.ts

@@ -18,6 +18,16 @@
             super(name, scene);
             this.direction = direction;
         }
+
+        protected _buildUniformLayout(): void {
+            this._uniformBuffer.addUniform("vLightData", 4);
+            this._uniformBuffer.addUniform("vLightDiffuse", 4);
+            this._uniformBuffer.addUniform("vLightSpecular", 3);
+            this._uniformBuffer.addUniform("vLightGround", 3);
+            this._uniformBuffer.addUniform("shadowsInfo", 3);
+            this._uniformBuffer.create();
+        }
+
         /**
          * Returns the string "HemisphericLight".  
          */
@@ -41,14 +51,15 @@
          * Sets the passed Effect object with the HemisphericLight normalized direction and color and the passed name (string).  
          * Returns the HemisphericLight.  
          */
-        public transferToEffect(effect: Effect, directionUniformName: string, groundColorUniformName: string): HemisphericLight {
+        public transferToEffect(effect: Effect, lightIndex: string): HemisphericLight {
             var normalizeDirection = Vector3.Normalize(this.direction);
-            effect.setFloat4(directionUniformName,
+            this._uniformBuffer.updateFloat4("vLightData",
                 normalizeDirection.x,
                 normalizeDirection.y,
                 normalizeDirection.z,
-                0.0);
-            effect.setColor3(groundColorUniformName, this.groundColor.scale(this.intensity));
+                0.0,
+                lightIndex);
+            this._uniformBuffer.updateColor3("vLightGround", this.groundColor.scale(this.intensity), lightIndex);
             return this;
         }
 

+ 13 - 1
src/Lights/babylon.light.ts

@@ -135,6 +135,9 @@
         public _excludedMeshesIds = new Array<string>();
         public _includedOnlyMeshesIds = new Array<string>();
 
+        // Light uniform buffer
+        public _uniformBuffer: UniformBuffer;
+
         /**
          * Creates a Light object in the scene.  
          * Documentation : http://doc.babylonjs.com/tutorials/lights  
@@ -142,12 +145,19 @@
         constructor(name: string, scene: Scene) {
             super(name, scene);
             this.getScene().addLight(this);
+            this._uniformBuffer = new UniformBuffer(scene.getEngine());
+            this._buildUniformLayout();
 
             this.includedOnlyMeshes = new Array<AbstractMesh>();
             this.excludedMeshes = new Array<AbstractMesh>();
 
             this._resyncMeshes();
         }
+
+        protected _buildUniformLayout(): void {
+            // Overridden
+        }
+
         /**
          * Returns the string "Light".  
          */
@@ -197,7 +207,7 @@
             return Vector3.Zero();
         }
 
-        public transferToEffect(effect: Effect, uniformName0?: string, uniformName1?: string): void {
+        public transferToEffect(effect: Effect, lightIndex: string): void {
         }
 
         public _getWorldMatrix(): Matrix {
@@ -271,6 +281,8 @@
                 mesh._removeLightSource(this);
             }
 
+            this._uniformBuffer.dispose();
+
             // Remove from scene
             this.getScene().removeLight(this);
             super.dispose();

+ 15 - 4
src/Lights/babylon.pointLight.ts

@@ -27,6 +27,15 @@
             super(name, scene);
             this.position = position;
         }
+
+        protected _buildUniformLayout(): void {
+            this._uniformBuffer.addUniform("vLightData", 4);
+            this._uniformBuffer.addUniform("vLightDiffuse", 4);
+            this._uniformBuffer.addUniform("vLightSpecular", 3);
+            this._uniformBuffer.addUniform("shadowsInfo", 3);
+            this._uniformBuffer.create();
+        }
+
         /**
          * Returns the string "PointLight"
          */
@@ -60,19 +69,21 @@
          * Sets the passed Effect "effect" with the PointLight transformed position (or position, if none) and passed name (string).  
          * Returns the PointLight.  
          */
-        public transferToEffect(effect: Effect, positionUniformName: string): PointLight {
+        public transferToEffect(effect: Effect, lightIndex: string): PointLight {
+
             if (this.parent && this.parent.getWorldMatrix) {
                 this.computeTransformedPosition();
 
-                effect.setFloat4(positionUniformName,
+                this._uniformBuffer.updateFloat4("vLightData",
                     this.transformedPosition.x,
                     this.transformedPosition.y,
                     this.transformedPosition.z,
-                    0.0); 
+                    0.0,
+                    lightIndex); 
                 return this;
             }
 
-            effect.setFloat4(positionUniformName, this.position.x, this.position.y, this.position.z, 0);
+            this._uniformBuffer.updateFloat4("vLightData", this.position.x, this.position.y, this.position.z, 0, lightIndex);
             return this;
         }
         /**

+ 20 - 7
src/Lights/babylon.spotLight.ts

@@ -42,6 +42,16 @@
             this.angle = angle;
             this.exponent = exponent;
         }
+
+        protected _buildUniformLayout(): void {
+            this._uniformBuffer.addUniform("vLightData", 4);
+            this._uniformBuffer.addUniform("vLightDiffuse", 4);
+            this._uniformBuffer.addUniform("vLightSpecular", 3);
+            this._uniformBuffer.addUniform("vLightDirection", 3);
+            this._uniformBuffer.addUniform("shadowsInfo", 3);
+            this._uniformBuffer.create();
+        }
+        
         /**
          * Returns the string "SpotLight".  
          */
@@ -119,7 +129,7 @@
          * Sets the passed Effect object with the SpotLight transfomed position (or position if not parented) and normalized direction.  
          * Return the SpotLight.   
          */
-        public transferToEffect(effect: Effect, positionUniformName: string, directionUniformName: string): SpotLight {
+        public transferToEffect(effect: Effect, lightIndex: string): SpotLight {
             var normalizeDirection;
 
             if (this.parent && this.parent.getWorldMatrix) {
@@ -131,28 +141,31 @@
                 
                 Vector3.TransformNormalToRef(this.direction, this.parent.getWorldMatrix(), this._transformedDirection);
 
-                effect.setFloat4(positionUniformName,
+                this._uniformBuffer.updateFloat4("vLightData",
                     this.transformedPosition.x,
                     this.transformedPosition.y,
                     this.transformedPosition.z,
-                    this.exponent);
+                    this.exponent,
+                    lightIndex);
 
                 normalizeDirection = Vector3.Normalize(this._transformedDirection);
             } else {
-                effect.setFloat4(positionUniformName,
+                this._uniformBuffer.updateFloat4("vLightData",
                     this.position.x,
                     this.position.y,
                     this.position.z,
-                    this.exponent);                    
+                    this.exponent,
+                    lightIndex);                    
 
                 normalizeDirection = Vector3.Normalize(this.direction);
             }
 
-            effect.setFloat4(directionUniformName,
+            this._uniformBuffer.updateFloat4("vLightDirection",
                 normalizeDirection.x,
                 normalizeDirection.y,
                 normalizeDirection.z,
-                Math.cos(this.angle * 0.5));
+                Math.cos(this.angle * 0.5),
+                lightIndex);
             return this;
         }
 

+ 53 - 2
src/Materials/babylon.effect.ts

@@ -74,12 +74,14 @@
     export class EffectCreationOptions {
         public attributes: string[];
         public uniformsNames: string[];
+        public uniformBuffersNames: string[];
         public samplers: string[];
-        public defines: string;
+        public defines: any;
         public fallbacks: EffectFallbacks;
         public onCompiled: (effect: Effect) => void;
         public onError: (effect: Effect, errors: string) => void;
         public indexParameters: any;
+        public maxSimultaneousLights: number;
     }
 
     export class Effect {
@@ -92,6 +94,7 @@
 
         private static _uniqueIdSeed = 0;
         private _engine: Engine;
+        private _uniformBuffersNames: { [key: string]: number } = {};
         private _uniformsNames: string[];
         private _samplers: string[];
         private _isReady = false;
@@ -105,6 +108,7 @@
 
         private _program: WebGLProgram;
         private _valueCache: { [key: string]: any } = {};
+        private static _baseCache: { [key: number]: WebGLBuffer } = {};
 
         constructor(baseName: any, attributesNamesOrOptions: string[] | EffectCreationOptions, uniformsNamesOrEngine: string[] | Engine, samplers?: string[], engine?: Engine, defines?: string, fallbacks?: EffectFallbacks, onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void, indexParameters?: any) {
             this.name = baseName;
@@ -120,7 +124,13 @@
                 this.onError = options.onError;
                 this.onCompiled = options.onCompiled;
                 this._fallbacks = options.fallbacks;
-                this._indexParameters = options.indexParameters;                
+                this._indexParameters = options.indexParameters;  
+
+                if (options.uniformBuffersNames) {
+                    for (var i = 0; i < options.uniformBuffersNames.length; i++) {
+                        this._uniformBuffersNames[options.uniformBuffersNames[i]] = i;
+                    }          
+                }    
             } else {
                 this._engine = engine;
                 this.defines = defines;
@@ -380,6 +390,16 @@
             while (match != null) {
                 var includeFile = match[1];
 
+                // Uniform declaration
+                if (includeFile.indexOf("__decl__") !== -1) {
+                    includeFile = includeFile.replace(/__decl__/, "");
+                    if (this._engine.webGLVersion != 1) {
+                        includeFile = includeFile.replace(/Vertex/, "Ubo");
+                        includeFile = includeFile.replace(/Fragment/, "Ubo");
+                    }
+                    includeFile = includeFile + "Declaration";
+                }
+
                 if (Effect.IncludesShadersStore[includeFile]) {
                     // Substitution
                     var includeContent = Effect.IncludesShadersStore[includeFile];
@@ -409,9 +429,21 @@
                             }
 
                             for (var i = minIndex; i < maxIndex; i++) {
+                                if (this._engine.webGLVersion === 1) {
+                                    // Ubo replacement
+                                    sourceIncludeContent = sourceIncludeContent.replace(/light\{X\}.(\w*)/g, (str: string, p1: string) => {
+                                        return p1 + "{X}";
+                                    });
+                                }
                                 includeContent += sourceIncludeContent.replace(/\{X\}/g, i) + "\n";
                             }
                         } else {
+                            if (this._engine.webGLVersion === 1) {
+                                // Ubo replacement
+                                includeContent = includeContent.replace(/light\{X\}.(\w*)/g, (str: string, p1: string) => {
+                                    return p1 + "{X}";
+                                });
+                            }
                             includeContent = includeContent.replace(/\{X\}/g, indexString);
                         }
                     }
@@ -456,6 +488,12 @@
 
                 this._program = engine.createShaderProgram(vertexSourceCode, fragmentSourceCode, defines);
 
+                if (engine.webGLVersion > 1) {
+                    for (var name in this._uniformBuffersNames) {
+                        this.bindUniformBlock(name, this._uniformBuffersNames[name]);
+                    }
+                }
+
                 this._uniforms = engine.getUniforms(this._program, this._uniformsNames);
                 this._attributes = engine.getAttributes(this._program, attributesNames);
 
@@ -617,6 +655,18 @@
             return changed;
         }
 
+        public bindUniformBuffer(buffer: WebGLBuffer, name: string): void {
+            if (Effect._baseCache[this._uniformBuffersNames[name]] === buffer) {
+                return;
+            }
+            Effect._baseCache[this._uniformBuffersNames[name]] = buffer;
+            this._engine.bindUniformBufferBase(buffer, this._uniformBuffersNames[name]);
+        }
+
+        public bindUniformBlock(blockName: string, index: number): void {
+            this._engine.bindUniformBlock(this._program, blockName, index);
+        }
+
         public setIntArray(uniformName: string, array: Int32Array): Effect {
             this._valueCache[uniformName] = null;
             this._engine.setIntArray(this.getUniform(uniformName), array);
@@ -796,6 +846,7 @@
         }
 
         public setColor3(uniformName: string, color3: Color3): Effect {
+
             if (this._cacheFloat3(uniformName, color3.r, color3.g, color3.b)) {
                 this._engine.setColor3(this.getUniform(uniformName), color3);
             }

+ 27 - 0
src/Materials/babylon.material.ts

@@ -332,10 +332,12 @@
 
         public _effect: Effect;
         public _wasPreviouslyReady = false;
+        private _useUBO: boolean;
         private _scene: Scene;
         private _fillMode = Material.TriangleFillMode;
         private _cachedDepthWriteState: boolean;
 
+        protected _uniformBuffer: UniformBuffer;
 
         constructor(name: string, scene: Scene, doNotAdd?: boolean) {
             this.name = name;
@@ -349,6 +351,9 @@
                 this.sideOrientation = Material.CounterClockWiseSideOrientation;
             }
 
+            this._uniformBuffer = new UniformBuffer(this._scene.getEngine());
+            this._useUBO = this.getScene().getEngine().webGLVersion > 1;
+
             if (!doNotAdd) {
                 this._scene.materials.push(this);
             }
@@ -438,6 +443,26 @@
         public bindOnlyWorldMatrix(world: Matrix): void {
         }
 
+        public bindSceneUniformBuffer(effect: Effect, sceneUbo: UniformBuffer): void {
+            sceneUbo.bindToEffect(effect, "Scene");
+        }
+
+        public bindView(effect: Effect): void {
+            if (!this._useUBO) {
+                effect.setMatrix("view", this.getScene().getViewMatrix());
+            } else {
+                this.bindSceneUniformBuffer(effect, this.getScene().getSceneUniformBuffer());
+            }
+        }
+
+        public bindViewProjection(effect: Effect): void {
+            if (!this._useUBO) {
+                effect.setMatrix("viewProjection", this.getScene().getTransformMatrix());
+            } else {
+                this.bindSceneUniformBuffer(effect, this.getScene().getSceneUniformBuffer());
+            }
+        }
+
         protected _afterBind(mesh: Mesh): void {
             this._scene._cachedMaterial = this;
 
@@ -509,6 +534,8 @@
                 }
             }
 
+            this._uniformBuffer.dispose();
+
             // Shader are kept in cache for further use but we can get rid of this by using forceDisposeEffect
             if (forceDisposeEffect && this._effect) {
                     if (this.storeEffectOnSubMeshes) {

+ 27 - 20
src/Materials/babylon.materialHelper.ts

@@ -190,7 +190,20 @@
             return needNormals;
         }
 
-        public static PrepareUniformsAndSamplersList(uniformsList: string[], samplersList: string[], defines: MaterialDefines, maxSimultaneousLights = 4): void {
+        public static PrepareUniformsAndSamplersList(uniformsListOrOptions: string[] | EffectCreationOptions, samplersList?: string[], defines?: MaterialDefines, maxSimultaneousLights = 4): void {
+            var uniformsList: string[], uniformBuffersList: string[], samplersList: string[], defines: MaterialDefines;
+
+            if ((<EffectCreationOptions>uniformsListOrOptions).uniformsNames) {
+                var options = <EffectCreationOptions>uniformsListOrOptions;
+                uniformsList = options.uniformsNames;
+                uniformBuffersList = options.uniformBuffersNames;
+                samplersList = options.samplers;
+                defines = options.defines;
+                maxSimultaneousLights = options.maxSimultaneousLights;
+            } else {
+                uniformsList = <string[]>uniformsListOrOptions;
+            }
+
             for (var lightIndex = 0; lightIndex < maxSimultaneousLights; lightIndex++) {
                 if (!defines["LIGHT" + lightIndex]) {
                     break;
@@ -206,6 +219,10 @@
                     "shadowsInfo" + lightIndex
                 );
 
+                if (uniformBuffersList) {
+                    uniformBuffersList.push("Light" + lightIndex);
+                }
+
                 samplersList.push("shadowSampler" + lightIndex);
             }
 
@@ -286,8 +303,9 @@
         }
 
         // Bindings
-        public static BindLightShadow(light: Light, scene: Scene, mesh: AbstractMesh, lightIndex: number, effect: Effect, depthValuesAlreadySet: boolean): boolean {
+        public static BindLightShadow(light: Light, scene: Scene, mesh: AbstractMesh, lightIndex: string, effect: Effect, depthValuesAlreadySet: boolean): boolean {
             var shadowGenerator = <ShadowGenerator>light.getShadowGenerator();
+
             if (mesh.receiveShadows && shadowGenerator) {
                 if (!(<any>light).needCube()) {
                     effect.setMatrix("lightMatrix" + lightIndex, shadowGenerator.getTransformMatrix());
@@ -298,26 +316,14 @@
                     }
                 }
                 effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMapForRendering());
-                effect.setFloat3("shadowsInfo" + lightIndex, shadowGenerator.getDarkness(), shadowGenerator.blurScale / shadowGenerator.getShadowMap().getSize().width, shadowGenerator.depthScale);
+                light._uniformBuffer.updateFloat3("shadowsInfo", shadowGenerator.getDarkness(), shadowGenerator.blurScale / shadowGenerator.getShadowMap().getSize().width, shadowGenerator.depthScale, lightIndex);
             }
 
             return depthValuesAlreadySet;
         }
 
         public static BindLightProperties(light: Light, effect: Effect, lightIndex: number): void {
-            if (light.getTypeID() === 0) {
-                // Point Light
-                light.transferToEffect(effect, "vLightData" + lightIndex);
-            } else if (light.getTypeID() === 1) {
-                // Directional Light
-                light.transferToEffect(effect, "vLightData" + lightIndex);
-            } else if (light.getTypeID() === 2) {
-                // Spot Light
-                light.transferToEffect(effect, "vLightData" + lightIndex, "vLightDirection" + lightIndex);
-            } else if (light.getTypeID() === 3) {
-                // Hemispheric Light
-                light.transferToEffect(effect, "vLightData" + lightIndex, "vLightGround" + lightIndex);
-            }
+            light.transferToEffect(effect, lightIndex + "");
         }
 
         public static BindLights(scene: Scene, mesh: AbstractMesh, effect: Effect, defines: MaterialDefines, maxSimultaneousLights = 4) {
@@ -325,21 +331,22 @@
             var depthValuesAlreadySet = false;
 
             for (var light of mesh._lightSources) {
+                light._uniformBuffer.bindToEffect(effect, "Light" + lightIndex);
 
                 MaterialHelper.BindLightProperties(light, effect, lightIndex);
 
                 light.diffuse.scaleToRef(light.intensity, Tmp.Color3[0]);
-                effect.setColor4("vLightDiffuse" + lightIndex, Tmp.Color3[0], light.range);
+                light._uniformBuffer.updateColor4("vLightDiffuse", Tmp.Color3[0], light.range, lightIndex + "");
                 if (defines["SPECULARTERM"]) {
                     light.specular.scaleToRef(light.intensity, Tmp.Color3[1]);
-                    effect.setColor3("vLightSpecular" + lightIndex, Tmp.Color3[1]);
+                    light._uniformBuffer.updateColor3("vLightSpecular", Tmp.Color3[1], lightIndex + "");
                 }
 
                 // Shadows
                 if (scene.shadowsEnabled) {
-                    depthValuesAlreadySet = this.BindLightShadow(light, scene, mesh, lightIndex, effect, depthValuesAlreadySet);
+                    depthValuesAlreadySet = this.BindLightShadow(light, scene, mesh, lightIndex + "", effect, depthValuesAlreadySet);
                 }
-
+                light._uniformBuffer.update();
                 lightIndex++;
 
                 if (lightIndex === maxSimultaneousLights)

+ 290 - 169
src/Materials/babylon.pbrMaterial.ts

@@ -635,26 +635,31 @@
             var lightIndex = 0;
             var depthValuesAlreadySet = false;
             for (var light of mesh._lightSources) {
+                var useUbo = light._uniformBuffer.useUbo;
+
+                light._uniformBuffer.bindToEffect(effect, "Light" + lightIndex);
                 MaterialHelper.BindLightProperties(light, effect, lightIndex);
 
                 // GAMMA CORRECTION.
                 this.convertColorToLinearSpaceToRef(light.diffuse, PBRMaterial._scaledAlbedo, useScalarInLinearSpace);
 
                 PBRMaterial._scaledAlbedo.scaleToRef(light.intensity, PBRMaterial._scaledAlbedo);
-                effect.setColor4("vLightDiffuse" + lightIndex, PBRMaterial._scaledAlbedo, usePhysicalLightFalloff ? light.radius : light.range);
+                light._uniformBuffer.updateColor4(useUbo ? "vLightDiffuse" : "vLightDiffuse" + lightIndex, PBRMaterial._scaledAlbedo, usePhysicalLightFalloff ? light.radius : light.range);
 
                 if (defines["SPECULARTERM"]) {
                     this.convertColorToLinearSpaceToRef(light.specular, PBRMaterial._scaledReflectivity, useScalarInLinearSpace);
 
                     PBRMaterial._scaledReflectivity.scaleToRef(light.intensity, PBRMaterial._scaledReflectivity);
-                    effect.setColor3("vLightSpecular" + lightIndex, PBRMaterial._scaledReflectivity);
+                    light._uniformBuffer.updateColor3(useUbo ? "vLightSpecular" : "vLightSpecular" + lightIndex, PBRMaterial._scaledReflectivity);
                 }
 
                 // Shadows
                 if (scene.shadowsEnabled) {
-                    depthValuesAlreadySet = MaterialHelper.BindLightShadow(light, scene, mesh, lightIndex, effect, depthValuesAlreadySet);
+                    depthValuesAlreadySet = MaterialHelper.BindLightShadow(light, scene, mesh, lightIndex + "", effect, depthValuesAlreadySet);
                 }
 
+                light._uniformBuffer.update();
+
                 lightIndex++;
 
                 if (lightIndex === maxSimultaneousLights)
@@ -1151,18 +1156,43 @@
                 ];
 
                 var samplers = ["albedoSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "reflectivitySampler", "microSurfaceSampler", "bumpSampler", "lightmapSampler", "refractionCubeSampler", "refraction2DSampler"];
-                
+                var uniformBuffers = ["Material", "Scene"];
+
                 if (this._defines.CAMERACOLORCURVES) {
                     ColorCurves.PrepareUniforms(uniforms);
                 }
                 if (this._defines.CAMERACOLORGRADING) {
                     ColorGradingTexture.PrepareUniformsAndSamplers(uniforms, samplers);
                 }
-                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, this._defines, this.maxSimultaneousLights); 
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: this._defines, 
+                    maxSimultaneousLights: this.maxSimultaneousLights
+                });
+
+                var onCompiled = function(effect) {
+                    if (this.onCompiled) {
+                        this.onCompiled(effect);
+                    }
+
+                    this.bindSceneUniformBuffer(effect, scene.getSceneUniformBuffer());
+                }.bind(this);
+                
+                this._effect = scene.getEngine().createEffect("pbr", <EffectCreationOptions>{
+                    attributes: attribs,
+                    uniformsNames: uniforms,
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers,
+                    defines: join,
+                    fallbacks: fallbacks,
+                    onCompiled: onCompiled,
+                    onError: this.onError,
+                    indexParameters: { maxSimultaneousLights: this.maxSimultaneousLights, maxSimultaneousMorphTargets: this._defines.NUM_MORPH_INFLUENCERS }
+                }, engine);
                 
-                this._effect = scene.getEngine().createEffect("pbr",
-                    attribs, uniforms, samplers,
-                    join, fallbacks, this.onCompiled, this.onError, {maxSimultaneousLights: this.maxSimultaneousLights, maxSimultaneousMorphTargets: this._defines.NUM_MORPH_INFLUENCERS});
+                this.buildUniformLayout();
             }
             if (!this._effect.isReady()) {
                 return false;
@@ -1174,14 +1204,61 @@
             return true;
         }
 
+        public buildUniformLayout(): void {
+            // Order is important !
+            this._uniformBuffer.addUniform("vAlbedoInfos", 2);
+            this._uniformBuffer.addUniform("vAmbientInfos", 3);
+            this._uniformBuffer.addUniform("vOpacityInfos", 2);
+            this._uniformBuffer.addUniform("vEmissiveInfos", 2);
+            this._uniformBuffer.addUniform("vLightmapInfos", 2);
+            this._uniformBuffer.addUniform("vReflectivityInfos", 3);
+            this._uniformBuffer.addUniform("vMicroSurfaceSamplerInfos", 2);
+            this._uniformBuffer.addUniform("vRefractionInfos", 4);
+            this._uniformBuffer.addUniform("vReflectionInfos", 2);
+            this._uniformBuffer.addUniform("vBumpInfos", 3);
+            this._uniformBuffer.addUniform("albedoMatrix", 16);
+            this._uniformBuffer.addUniform("ambientMatrix", 16);
+            this._uniformBuffer.addUniform("opacityMatrix", 16);
+            this._uniformBuffer.addUniform("emissiveMatrix", 16);
+            this._uniformBuffer.addUniform("lightmapMatrix", 16);
+            this._uniformBuffer.addUniform("reflectivityMatrix", 16);
+            this._uniformBuffer.addUniform("microSurfaceSamplerMatrix", 16);
+            this._uniformBuffer.addUniform("bumpMatrix", 16);
+            this._uniformBuffer.addUniform("refractionMatrix", 16);
+            this._uniformBuffer.addUniform("reflectionMatrix", 16);
+
+            this._uniformBuffer.addUniform("vReflectionColor", 3);
+            this._uniformBuffer.addUniform("vAlbedoColor", 4);
+            this._uniformBuffer.addUniform("vLightingIntensity", 4);
+
+            this._uniformBuffer.addUniform("vMicrosurfaceTextureLods", 2);
+            this._uniformBuffer.addUniform("vReflectivityColor", 4);
+            this._uniformBuffer.addUniform("vEmissiveColor", 3);
+            this._uniformBuffer.addUniform("opacityParts", 4);
+            this._uniformBuffer.addUniform("emissiveLeftColor", 4);
+            this._uniformBuffer.addUniform("emissiveRightColor", 4);
+
+            this._uniformBuffer.addUniform("vOverloadedIntensity", 4);
+            this._uniformBuffer.addUniform("vOverloadedAmbient", 3);
+            this._uniformBuffer.addUniform("vOverloadedAlbedo", 3);
+            this._uniformBuffer.addUniform("vOverloadedReflectivity", 3);
+            this._uniformBuffer.addUniform("vOverloadedEmissive", 3);
+            this._uniformBuffer.addUniform("vOverloadedReflection", 3);
+            this._uniformBuffer.addUniform("vOverloadedMicroSurface", 3);
+            this._uniformBuffer.addUniform("vOverloadedShadowIntensity", 4);
+
+            this._uniformBuffer.addUniform("pointSize", 1);
+            this._uniformBuffer.create();
+        }
+
 
         public unbind(): void {
             if (this.reflectionTexture && this.reflectionTexture.isRenderTarget) {
-                this._effect.setTexture("reflection2DSampler", null);
+                this._uniformBuffer.setTexture("reflection2DSampler", null);
             }
 
             if (this.refractionTexture && this.refractionTexture.isRenderTarget) {
-                this._effect.setTexture("refraction2DSampler", null);
+                this._uniformBuffer.setTexture("refraction2DSampler", null);
             }
 
             super.unbind();
@@ -1196,7 +1273,7 @@
 
         public bind(world: Matrix, mesh?: Mesh): void {
             this._myScene = this.getScene();
-
+            var effect = this._effect;
             // Matrices        
             this.bindOnlyWorldMatrix(world);
 
@@ -1204,149 +1281,249 @@
             MaterialHelper.BindBonesParameters(mesh, this._effect);
 
             if (this._myScene.getCachedMaterial() !== (<BABYLON.Material>this)) {
-                this._effect.setMatrix("viewProjection", this._myScene.getTransformMatrix());
+                this._uniformBuffer.bindToEffect(effect, "Material");
 
-                if (StandardMaterial.FresnelEnabled) {
-                    if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
-                        this._effect.setColor4("opacityParts", new Color3(this.opacityFresnelParameters.leftColor.toLuminance(), this.opacityFresnelParameters.rightColor.toLuminance(), this.opacityFresnelParameters.bias), this.opacityFresnelParameters.power);
+                this.bindViewProjection(effect);
+
+                if (!this._uniformBuffer.useUbo || !this.isFrozen || !this._uniformBuffer.isSync) {
+
+                    // Fresnel
+                    if (StandardMaterial.FresnelEnabled) {
+                        if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                            this._uniformBuffer.updateColor4("opacityParts", new Color3(this.opacityFresnelParameters.leftColor.toLuminance(), this.opacityFresnelParameters.rightColor.toLuminance(), this.opacityFresnelParameters.bias), this.opacityFresnelParameters.power);
+                        }
+
+                        if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                            this._uniformBuffer.updateColor4("emissiveLeftColor", this.emissiveFresnelParameters.leftColor, this.emissiveFresnelParameters.power);
+                            this._uniformBuffer.updateColor4("emissiveRightColor", this.emissiveFresnelParameters.rightColor, this.emissiveFresnelParameters.bias);
+                        }
                     }
 
-                    if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
-                        this._effect.setColor4("emissiveLeftColor", this.emissiveFresnelParameters.leftColor, this.emissiveFresnelParameters.power);
-                        this._effect.setColor4("emissiveRightColor", this.emissiveFresnelParameters.rightColor, this.emissiveFresnelParameters.bias);
+                    // Texture uniforms      
+                    if (this._myScene.texturesEnabled) {
+                        if (this.albedoTexture && StandardMaterial.DiffuseTextureEnabled) {
+                            this._uniformBuffer.updateFloat2("vAlbedoInfos", this.albedoTexture.coordinatesIndex, this.albedoTexture.level);
+                            this._uniformBuffer.updateMatrix("albedoMatrix", this.albedoTexture.getTextureMatrix());
+                        }
+
+                        if (this.ambientTexture && StandardMaterial.AmbientTextureEnabled) {
+                            this._uniformBuffer.updateFloat3("vAmbientInfos", this.ambientTexture.coordinatesIndex, this.ambientTexture.level, this.ambientTextureStrength);
+                            this._uniformBuffer.updateMatrix("ambientMatrix", this.ambientTexture.getTextureMatrix());
+                        }
+
+                        if (this.opacityTexture && StandardMaterial.OpacityTextureEnabled) {
+                            this._uniformBuffer.updateFloat2("vOpacityInfos", this.opacityTexture.coordinatesIndex, this.opacityTexture.level);
+                            this._uniformBuffer.updateMatrix("opacityMatrix", this.opacityTexture.getTextureMatrix());
+                        }
+
+                        if (this.reflectionTexture && StandardMaterial.ReflectionTextureEnabled) {
+                            this._microsurfaceTextureLods.x = Math.round(Math.log(this.reflectionTexture.getSize().width) * Math.LOG2E);
+                            this._uniformBuffer.updateMatrix("reflectionMatrix", this.reflectionTexture.getReflectionTextureMatrix());
+                            this._uniformBuffer.updateFloat2("vReflectionInfos", this.reflectionTexture.level, 0);
+
+                            if (this._defines.USESPHERICALFROMREFLECTIONMAP) {
+                                this._effect.setFloat3("vSphericalX", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.x.x,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.x.y,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.x.z);
+                                this._effect.setFloat3("vSphericalY", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.y.x,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.y.y,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.y.z);
+                                this._effect.setFloat3("vSphericalZ", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.z.x,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.z.y,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.z.z);
+                                this._effect.setFloat3("vSphericalXX", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.xx.x,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.xx.y,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.xx.z);
+                                this._effect.setFloat3("vSphericalYY", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.yy.x,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.yy.y,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.yy.z);
+                                this._effect.setFloat3("vSphericalZZ", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.zz.x,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.zz.y,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.zz.z);
+                                this._effect.setFloat3("vSphericalXY", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.xy.x,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.xy.y,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.xy.z);
+                                this._effect.setFloat3("vSphericalYZ", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.yz.x,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.yz.y,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.yz.z);
+                                this._effect.setFloat3("vSphericalZX", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.zx.x,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.zx.y,
+                                    (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.zx.z);
+                            }
+                        }
+
+                        if (this.emissiveTexture && StandardMaterial.EmissiveTextureEnabled) {
+                            this._uniformBuffer.updateFloat2("vEmissiveInfos", this.emissiveTexture.coordinatesIndex, this.emissiveTexture.level);
+                            this._uniformBuffer.updateMatrix("emissiveMatrix", this.emissiveTexture.getTextureMatrix());
+                        }
+
+                        if (this.lightmapTexture && StandardMaterial.LightmapTextureEnabled) {
+                            this._uniformBuffer.updateFloat2("vLightmapInfos", this.lightmapTexture.coordinatesIndex, this.lightmapTexture.level);
+                            this._uniformBuffer.updateMatrix("lightmapMatrix", this.lightmapTexture.getTextureMatrix());
+                        }
+
+                        if (StandardMaterial.SpecularTextureEnabled) {
+                            if (this.metallicTexture) {
+                                this._uniformBuffer.updateFloat3("vReflectivityInfos", this.metallicTexture.coordinatesIndex, this.metallicTexture.level, this.ambientTextureStrength);
+                                this._uniformBuffer.updateMatrix("reflectivityMatrix", this.metallicTexture.getTextureMatrix());
+                            }
+                            else if (this.reflectivityTexture) {
+                                this._uniformBuffer.updateFloat3("vReflectivityInfos", this.reflectivityTexture.coordinatesIndex, this.reflectivityTexture.level, 1.0);
+                                this._uniformBuffer.updateMatrix("reflectivityMatrix", this.reflectivityTexture.getTextureMatrix());
+                            }
+
+                            if (this.microSurfaceTexture) {
+                                this._uniformBuffer.updateFloat2("vMicroSurfaceSamplerInfos", this.microSurfaceTexture.coordinatesIndex, this.microSurfaceTexture.level);
+                                this._uniformBuffer.updateMatrix("microSurfaceSamplerMatrix", this.microSurfaceTexture.getTextureMatrix());
+                            }
+                        }
+
+                        if (this.bumpTexture && this._myScene.getEngine().getCaps().standardDerivatives && StandardMaterial.BumpTextureEnabled && !this.disableBumpMap) {
+                            this._uniformBuffer.updateFloat3("vBumpInfos", this.bumpTexture.coordinatesIndex, 1.0 / this.bumpTexture.level, this.parallaxScaleBias);
+                            this._uniformBuffer.updateMatrix("bumpMatrix", this.bumpTexture.getTextureMatrix());
+                        }
+
+                        if (this.refractionTexture && StandardMaterial.RefractionTextureEnabled) {
+                            this._microsurfaceTextureLods.y = Math.round(Math.log(this.refractionTexture.getSize().width) * Math.LOG2E);
+
+                            var depth = 1.0;
+                            if (!this.refractionTexture.isCube) {
+                                this._uniformBuffer.updateMatrix("refractionMatrix", this.refractionTexture.getReflectionTextureMatrix());
+
+                                if ((<any>this.refractionTexture).depth) {
+                                    depth = (<any>this.refractionTexture).depth;
+                                }
+                            }
+                            this._uniformBuffer.updateFloat4("vRefractionInfos", this.refractionTexture.level, this.indexOfRefraction, depth, this.invertRefractionY ? -1 : 1);
+                        }
+
+                        if ((this.reflectionTexture || this.refractionTexture)) {
+                            this._uniformBuffer.updateFloat2("vMicrosurfaceTextureLods", this._microsurfaceTextureLods.x, this._microsurfaceTextureLods.y);
+                        }
                     }
+
+                    // Point size
+                    if (this.pointsCloud) {
+                        this._uniformBuffer.updateFloat("pointSize", this.pointSize);
+                    }
+
+                    // Colors
+                    if (this._defines.METALLICWORKFLOW) {
+                        PBRMaterial._scaledReflectivity.r = (this.metallic === undefined || this.metallic === null) ? 1 : this.metallic;
+                        PBRMaterial._scaledReflectivity.g = (this.roughness === undefined || this.roughness === null) ? 1 : this.roughness;
+                        this._uniformBuffer.updateColor4("vReflectivityColor", PBRMaterial._scaledReflectivity, 0);
+                    }
+                    else {
+                        // GAMMA CORRECTION.
+                        this.convertColorToLinearSpaceToRef(this.reflectivityColor, PBRMaterial._scaledReflectivity);
+                        this._uniformBuffer.updateColor4("vReflectivityColor", PBRMaterial._scaledReflectivity, this.microSurface);
+                    }
+
+                    // GAMMA CORRECTION.
+                    this.convertColorToLinearSpaceToRef(this.emissiveColor, PBRMaterial._scaledEmissive);
+                    this._uniformBuffer.updateColor3("vEmissiveColor", PBRMaterial._scaledEmissive);
+
+                    // GAMMA CORRECTION.
+                    this.convertColorToLinearSpaceToRef(this.reflectionColor, PBRMaterial._scaledReflection);
+                    this._uniformBuffer.updateColor3("vReflectionColor", PBRMaterial._scaledReflection);
+
+                    // GAMMA CORRECTION.
+                    this.convertColorToLinearSpaceToRef(this.albedoColor, PBRMaterial._scaledAlbedo);
+                    this._uniformBuffer.updateColor4("vAlbedoColor", PBRMaterial._scaledAlbedo, this.alpha * mesh.visibility);
+
+
+                    // Misc
+                    this._lightingInfos.x = this.directIntensity;
+                    this._lightingInfos.y = this.emissiveIntensity;
+                    this._lightingInfos.z = this.environmentIntensity;
+                    this._lightingInfos.w = this.specularIntensity;
+
+                    this._uniformBuffer.updateVector4("vLightingIntensity", this._lightingInfos);
+
+                    // Overloaded params
+
+                    this._overloadedShadowInfos.x = this.overloadedShadowIntensity;
+                    this._overloadedShadowInfos.y = this.overloadedShadeIntensity;
+                    this._uniformBuffer.updateVector4("vOverloadedShadowIntensity", this._overloadedShadowInfos);
+
+                    this._overloadedIntensity.x = this.overloadedAmbientIntensity;
+                    this._overloadedIntensity.y = this.overloadedAlbedoIntensity;
+                    this._overloadedIntensity.z = this.overloadedReflectivityIntensity;
+                    this._overloadedIntensity.w = this.overloadedEmissiveIntensity;
+                    this._uniformBuffer.updateVector4("vOverloadedIntensity", this._overloadedIntensity);
+
+                    this._uniformBuffer.updateColor3("vOverloadedAmbient", this.overloadedAmbient);
+                    this.convertColorToLinearSpaceToRef(this.overloadedAlbedo, this._tempColor);
+                    this._uniformBuffer.updateColor3("vOverloadedAlbedo", this._tempColor);
+                    this.convertColorToLinearSpaceToRef(this.overloadedReflectivity, this._tempColor);
+                    this._uniformBuffer.updateColor3("vOverloadedReflectivity", this._tempColor);
+                    this.convertColorToLinearSpaceToRef(this.overloadedEmissive, this._tempColor);
+                    this._uniformBuffer.updateColor3("vOverloadedEmissive", this._tempColor);
+                    this.convertColorToLinearSpaceToRef(this.overloadedReflection, this._tempColor);
+                    this._uniformBuffer.updateColor3("vOverloadedReflection", this._tempColor);
+
+                    this._overloadedMicroSurface.x = this.overloadedMicroSurface;
+                    this._overloadedMicroSurface.y = this.overloadedMicroSurfaceIntensity;
+                    this._overloadedMicroSurface.z = this.overloadedReflectionIntensity;
+                    this._uniformBuffer.updateVector3("vOverloadedMicroSurface", this._overloadedMicroSurface);
+
                 }
 
                 // Textures        
                 if (this._myScene.texturesEnabled) {
                     if (this.albedoTexture && StandardMaterial.DiffuseTextureEnabled) {
-                        this._effect.setTexture("albedoSampler", this.albedoTexture);
-
-                        this._effect.setFloat2("vAlbedoInfos", this.albedoTexture.coordinatesIndex, this.albedoTexture.level);
-                        this._effect.setMatrix("albedoMatrix", this.albedoTexture.getTextureMatrix());
+                        this._uniformBuffer.setTexture("albedoSampler", this.albedoTexture);
                     }
 
                     if (this.ambientTexture && StandardMaterial.AmbientTextureEnabled) {
-                        this._effect.setTexture("ambientSampler", this.ambientTexture);
-
-                        this._effect.setFloat3("vAmbientInfos", this.ambientTexture.coordinatesIndex, this.ambientTexture.level, this.ambientTextureStrength);
-                        this._effect.setMatrix("ambientMatrix", this.ambientTexture.getTextureMatrix());
+                        this._uniformBuffer.setTexture("ambientSampler", this.ambientTexture);
                     }
 
                     if (this.opacityTexture && StandardMaterial.OpacityTextureEnabled) {
-                        this._effect.setTexture("opacitySampler", this.opacityTexture);
-
-                        this._effect.setFloat2("vOpacityInfos", this.opacityTexture.coordinatesIndex, this.opacityTexture.level);
-                        this._effect.setMatrix("opacityMatrix", this.opacityTexture.getTextureMatrix());
+                        this._uniformBuffer.setTexture("opacitySampler", this.opacityTexture);
                     }
 
                     if (this.reflectionTexture && StandardMaterial.ReflectionTextureEnabled) {
-                        this._microsurfaceTextureLods.x = Math.round(Math.log(this.reflectionTexture.getSize().width) * Math.LOG2E);
-
                         if (this.reflectionTexture.isCube) {
-                            this._effect.setTexture("reflectionCubeSampler", this.reflectionTexture);
+                            this._uniformBuffer.setTexture("reflectionCubeSampler", this.reflectionTexture);
                         } else {
-                            this._effect.setTexture("reflection2DSampler", this.reflectionTexture);
-                        }
-
-                        this._effect.setMatrix("reflectionMatrix", this.reflectionTexture.getReflectionTextureMatrix());
-                        this._effect.setFloat2("vReflectionInfos", this.reflectionTexture.level, 0);
-
-                        if (this._defines.USESPHERICALFROMREFLECTIONMAP) {
-                            this._effect.setFloat3("vSphericalX", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.x.x,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.x.y,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.x.z);
-                            this._effect.setFloat3("vSphericalY", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.y.x,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.y.y,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.y.z);
-                            this._effect.setFloat3("vSphericalZ", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.z.x,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.z.y,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.z.z);
-                            this._effect.setFloat3("vSphericalXX", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.xx.x,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.xx.y,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.xx.z);
-                            this._effect.setFloat3("vSphericalYY", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.yy.x,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.yy.y,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.yy.z);
-                            this._effect.setFloat3("vSphericalZZ", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.zz.x,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.zz.y,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.zz.z);
-                            this._effect.setFloat3("vSphericalXY", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.xy.x,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.xy.y,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.xy.z);
-                            this._effect.setFloat3("vSphericalYZ", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.yz.x,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.yz.y,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.yz.z);
-                            this._effect.setFloat3("vSphericalZX", (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.zx.x,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.zx.y,
-                                (<HDRCubeTexture>this.reflectionTexture).sphericalPolynomial.zx.z);
+                            this._uniformBuffer.setTexture("reflection2DSampler", this.reflectionTexture);
                         }
                     }
 
                     if (this.emissiveTexture && StandardMaterial.EmissiveTextureEnabled) {
-                        this._effect.setTexture("emissiveSampler", this.emissiveTexture);
-
-                        this._effect.setFloat2("vEmissiveInfos", this.emissiveTexture.coordinatesIndex, this.emissiveTexture.level);
-                        this._effect.setMatrix("emissiveMatrix", this.emissiveTexture.getTextureMatrix());
+                        this._uniformBuffer.setTexture("emissiveSampler", this.emissiveTexture);
                     }
 
                     if (this.lightmapTexture && StandardMaterial.LightmapTextureEnabled) {
-                        this._effect.setTexture("lightmapSampler", this.lightmapTexture);
-
-                        this._effect.setFloat2("vLightmapInfos", this.lightmapTexture.coordinatesIndex, this.lightmapTexture.level);
-                        this._effect.setMatrix("lightmapMatrix", this.lightmapTexture.getTextureMatrix());
+                        this._uniformBuffer.setTexture("lightmapSampler", this.lightmapTexture);
                     }
 
                     if (StandardMaterial.SpecularTextureEnabled) {
                         if (this.metallicTexture) {
-                            this._effect.setTexture("reflectivitySampler", this.metallicTexture);
-
-                            this._effect.setFloat3("vReflectivityInfos", this.metallicTexture.coordinatesIndex, this.metallicTexture.level, this.ambientTextureStrength);
-                            this._effect.setMatrix("reflectivityMatrix", this.metallicTexture.getTextureMatrix());
+                            this._uniformBuffer.setTexture("reflectivitySampler", this.metallicTexture);
                         }
                         else if (this.reflectivityTexture) {
-                            this._effect.setTexture("reflectivitySampler", this.reflectivityTexture);
-
-                            this._effect.setFloat3("vReflectivityInfos", this.reflectivityTexture.coordinatesIndex, this.reflectivityTexture.level, 1.0);
-                            this._effect.setMatrix("reflectivityMatrix", this.reflectivityTexture.getTextureMatrix());
+                            this._uniformBuffer.setTexture("reflectivitySampler", this.reflectivityTexture);
                         }
 
                         if (this.microSurfaceTexture) {
-                            this._effect.setTexture("microSurfaceSampler", this.microSurfaceTexture);
-
-                            this._effect.setFloat2("vMicroSurfaceSamplerInfos", this.microSurfaceTexture.coordinatesIndex, this.microSurfaceTexture.level);
-                            this._effect.setMatrix("microSurfaceSamplerMatrix", this.microSurfaceTexture.getTextureMatrix());
+                            this._uniformBuffer.setTexture("microSurfaceSampler", this.microSurfaceTexture);
                         }
                     }
 
                     if (this.bumpTexture && this._myScene.getEngine().getCaps().standardDerivatives && StandardMaterial.BumpTextureEnabled && !this.disableBumpMap) {
-                        this._effect.setTexture("bumpSampler", this.bumpTexture);
-
-                        this._effect.setFloat3("vBumpInfos", this.bumpTexture.coordinatesIndex, 1.0 / this.bumpTexture.level, this.parallaxScaleBias);
-                        this._effect.setMatrix("bumpMatrix", this.bumpTexture.getTextureMatrix());
+                        this._uniformBuffer.setTexture("bumpSampler", this.bumpTexture);
                     }
 
                     if (this.refractionTexture && StandardMaterial.RefractionTextureEnabled) {
-                        this._microsurfaceTextureLods.y = Math.round(Math.log(this.refractionTexture.getSize().width) * Math.LOG2E);
-
-                        var depth = 1.0;
                         if (this.refractionTexture.isCube) {
-                            this._effect.setTexture("refractionCubeSampler", this.refractionTexture);
+                            this._uniformBuffer.setTexture("refractionCubeSampler", this.refractionTexture);
                         } else {
-                            this._effect.setTexture("refraction2DSampler", this.refractionTexture);
-                            this._effect.setMatrix("refractionMatrix", this.refractionTexture.getReflectionTextureMatrix());
-
-                            if ((<any>this.refractionTexture).depth) {
-                                depth = (<any>this.refractionTexture).depth;
-                            }
+                            this._uniformBuffer.setTexture("refraction2DSampler", this.refractionTexture);
                         }
-                        this._effect.setFloat4("vRefractionInfos", this.refractionTexture.level, this.indexOfRefraction, depth, this.invertRefractionY ? -1 : 1);
                     }
 
-                    if ((this.reflectionTexture || this.refractionTexture)) {
-                        this._effect.setFloat2("vMicrosurfaceTextureLods", this._microsurfaceTextureLods.x, this._microsurfaceTextureLods.y);
-                    }
-                    
                     if (this.cameraColorGradingTexture && StandardMaterial.ColorGradingTextureEnabled) {
                         ColorGradingTexture.Bind(this.cameraColorGradingTexture, this._effect);
                     }
@@ -1355,41 +1532,14 @@
                 // Clip plane
                 MaterialHelper.BindClipPlane(this._effect, this._myScene);
 
-                // Point size
-                if (this.pointsCloud) {
-                    this._effect.setFloat("pointSize", this.pointSize);
-                }
-
                 // Colors
                 this._myScene.ambientColor.multiplyToRef(this.ambientColor, this._globalAmbientColor);
 
-                if (this._defines.METALLICWORKFLOW) {
-                    PBRMaterial._scaledReflectivity.r = (this.metallic === undefined || this.metallic === null) ? 1 : this.metallic;
-                    PBRMaterial._scaledReflectivity.g = (this.roughness === undefined || this.roughness === null) ? 1 : this.roughness;
-                    this._effect.setColor4("vReflectivityColor", PBRMaterial._scaledReflectivity, 0);
-                }
-                else {
-                    // GAMMA CORRECTION.
-                    this.convertColorToLinearSpaceToRef(this.reflectivityColor, PBRMaterial._scaledReflectivity);
-                    this._effect.setColor4("vReflectivityColor", PBRMaterial._scaledReflectivity, this.microSurface);
-                }
-
-                this._effect.setVector3("vEyePosition", this._myScene._mirroredCameraPosition ? this._myScene._mirroredCameraPosition : this._myScene.activeCamera.position);
-                this._effect.setColor3("vAmbientColor", this._globalAmbientColor);
-
-                // GAMMA CORRECTION.
-                this.convertColorToLinearSpaceToRef(this.emissiveColor, PBRMaterial._scaledEmissive);
-                this._effect.setColor3("vEmissiveColor", PBRMaterial._scaledEmissive);
-
-                // GAMMA CORRECTION.
-                this.convertColorToLinearSpaceToRef(this.reflectionColor, PBRMaterial._scaledReflection);
-                this._effect.setColor3("vReflectionColor", PBRMaterial._scaledReflection);
+                effect.setVector3("vEyePosition", this._myScene._mirroredCameraPosition ? this._myScene._mirroredCameraPosition : this._myScene.activeCamera.position);
+                effect.setColor3("vAmbientColor", this._globalAmbientColor);
             }
 
             if (this._myScene.getCachedMaterial() !== this || !this.isFrozen) {
-                // GAMMA CORRECTION.
-                this.convertColorToLinearSpaceToRef(this.albedoColor, PBRMaterial._scaledAlbedo);
-                this._effect.setColor4("vAlbedoColor", PBRMaterial._scaledAlbedo, this.alpha * mesh.visibility);
 
                 // Lights
                 if (this._myScene.lightsEnabled && !this.disableLighting) {
@@ -1398,7 +1548,7 @@
 
                 // View
                 if (this._myScene.fogEnabled && mesh.applyFog && this._myScene.fogMode !== Scene.FOGMODE_NONE || this.reflectionTexture) {
-                    this._effect.setMatrix("view", this._myScene.getViewMatrix());
+                    this.bindView(effect);
                 }
 
                 // Fog
@@ -1409,49 +1559,20 @@
                     MaterialHelper.BindMorphTargetParameters(mesh, this._effect);                
                 }
 
-                this._lightingInfos.x = this.directIntensity;
-                this._lightingInfos.y = this.emissiveIntensity;
-                this._lightingInfos.z = this.environmentIntensity;
-                this._lightingInfos.w = this.specularIntensity;
-
-                this._effect.setVector4("vLightingIntensity", this._lightingInfos);
-
-                this._overloadedShadowInfos.x = this.overloadedShadowIntensity;
-                this._overloadedShadowInfos.y = this.overloadedShadeIntensity;
-                this._effect.setVector4("vOverloadedShadowIntensity", this._overloadedShadowInfos);
-
                 this._cameraInfos.x = this.cameraExposure;
                 this._cameraInfos.y = this.cameraContrast;
-                this._effect.setVector4("vCameraInfos", this._cameraInfos);
+                effect.setVector4("vCameraInfos", this._cameraInfos);
                 
                 if (this.cameraColorCurves) {
                     ColorCurves.Bind(this.cameraColorCurves, this._effect);
                 }
 
-                this._overloadedIntensity.x = this.overloadedAmbientIntensity;
-                this._overloadedIntensity.y = this.overloadedAlbedoIntensity;
-                this._overloadedIntensity.z = this.overloadedReflectivityIntensity;
-                this._overloadedIntensity.w = this.overloadedEmissiveIntensity;
-                this._effect.setVector4("vOverloadedIntensity", this._overloadedIntensity);
-
-                this._effect.setColor3("vOverloadedAmbient", this.overloadedAmbient);
-                this.convertColorToLinearSpaceToRef(this.overloadedAlbedo, this._tempColor);
-                this._effect.setColor3("vOverloadedAlbedo", this._tempColor);
-                this.convertColorToLinearSpaceToRef(this.overloadedReflectivity, this._tempColor);
-                this._effect.setColor3("vOverloadedReflectivity", this._tempColor);
-                this.convertColorToLinearSpaceToRef(this.overloadedEmissive, this._tempColor);
-                this._effect.setColor3("vOverloadedEmissive", this._tempColor);
-                this.convertColorToLinearSpaceToRef(this.overloadedReflection, this._tempColor);
-                this._effect.setColor3("vOverloadedReflection", this._tempColor);
-
-                this._overloadedMicroSurface.x = this.overloadedMicroSurface;
-                this._overloadedMicroSurface.y = this.overloadedMicroSurfaceIntensity;
-                this._overloadedMicroSurface.z = this.overloadedReflectionIntensity;
-                this._effect.setVector3("vOverloadedMicroSurface", this._overloadedMicroSurface);
-
                 // Log. depth
                 MaterialHelper.BindLogDepth(this._defines, this._effect, this._myScene);
             }
+
+            this._uniformBuffer.update();
+
             this._afterBind(mesh);
 
             this._myScene = null;

+ 0 - 1
src/Materials/babylon.pushMaterial.ts

@@ -24,7 +24,6 @@
             return this.isReadyForSubMesh(mesh, mesh.subMeshes[0], useInstances);
         }
 
-        
         public bindOnlyWorldMatrix(world: Matrix): void {
             this._activeEffect.setMatrix("world", world);
         }

+ 11 - 5
src/Materials/babylon.shaderMaterial.ts

@@ -26,6 +26,7 @@
             options.needAlphaTesting = options.needAlphaTesting || false;
             options.attributes = options.attributes || ["position", "normal", "uv"];
             options.uniforms = options.uniforms || ["worldViewProjection"];
+            options.uniformBuffers = options.uniformBuffers || [];
             options.samplers = options.samplers || [];
             options.defines = options.defines || [];
 
@@ -205,11 +206,16 @@
             var previousEffect = this._effect;
             var join = defines.join("\n");
 
-            this._effect = engine.createEffect(this._shaderPath,
-                this._options.attributes,
-                this._options.uniforms,
-                this._options.samplers,
-                join, fallbacks, this.onCompiled, this.onError);
+            this._effect = engine.createEffect(this._shaderPath, <EffectCreationOptions>{
+                    attributes: this._options.attributes,
+                    uniformsNames: this._options.uniforms,
+                    uniformBuffersNames: this._options.uniformBuffers,
+                    samplers: this._options.samplers,
+                    defines: join,
+                    fallbacks: fallbacks,
+                    onCompiled: this.onCompiled,
+                    onError: this.onError
+                }, engine);
 
             if (!this._effect.isReady()) {
                 return false;

+ 149 - 71
src/Materials/babylon.standardMaterial.ts

@@ -710,6 +710,7 @@ module BABYLON {
                 ];
 
                 var samplers = ["diffuseSampler", "ambientSampler", "opacitySampler", "reflectionCubeSampler", "reflection2DSampler", "emissiveSampler", "specularSampler", "bumpSampler", "lightmapSampler", "refractionCubeSampler", "refraction2DSampler"]
+                var uniformBuffers = ["Material", "Scene"];
 
                 if (defines.CAMERACOLORCURVES) {
                     ColorCurves.PrepareUniforms(uniforms);
@@ -717,11 +718,18 @@ module BABYLON {
                 if (defines.CAMERACOLORGRADING) {
                     ColorGradingTexture.PrepareUniformsAndSamplers(uniforms, samplers);
                 }
-                MaterialHelper.PrepareUniformsAndSamplersList(uniforms, samplers, defines, this._maxSimultaneousLights);
-
-                subMesh.setEffect(scene.getEngine().createEffect(shaderName, {
+                MaterialHelper.PrepareUniformsAndSamplersList(<EffectCreationOptions>{
+                    uniformsNames: uniforms, 
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers, 
+                    defines: defines, 
+                    maxSimultaneousLights: this._maxSimultaneousLights
+                });
+
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, <EffectCreationOptions>{
                     attributes: attribs,
                     uniformsNames: uniforms,
+                    uniformBuffersNames: uniformBuffers,
                     samplers: samplers,
                     defines: join,
                     fallbacks: fallbacks,
@@ -729,6 +737,8 @@ module BABYLON {
                     onError: this.onError,
                     indexParameters: { maxSimultaneousLights: this._maxSimultaneousLights, maxSimultaneousMorphTargets: defines.NUM_MORPH_INFLUENCERS }
                 }, engine), defines);
+                
+                this.buildUniformLayout();
             }
 
             if (!subMesh.effect.isReady()) {
@@ -741,6 +751,45 @@ module BABYLON {
             return true;
         }
 
+        public buildUniformLayout(): void {
+            // Order is important !
+            this._uniformBuffer.addUniform("diffuseLeftColor", 4);
+            this._uniformBuffer.addUniform("diffuseRightColor", 4);
+            this._uniformBuffer.addUniform("opacityParts", 4);
+            this._uniformBuffer.addUniform("reflectionLeftColor", 4);
+            this._uniformBuffer.addUniform("reflectionRightColor", 4);
+            this._uniformBuffer.addUniform("refractionLeftColor", 4);
+            this._uniformBuffer.addUniform("refractionRightColor", 4);
+            this._uniformBuffer.addUniform("emissiveLeftColor", 4);
+            this._uniformBuffer.addUniform("emissiveRightColor", 4);
+
+            this._uniformBuffer.addUniform("vDiffuseInfos", 2);
+            this._uniformBuffer.addUniform("vAmbientInfos", 2);
+            this._uniformBuffer.addUniform("vOpacityInfos", 2);
+            this._uniformBuffer.addUniform("vReflectionInfos", 2);
+            this._uniformBuffer.addUniform("vEmissiveInfos", 2);
+            this._uniformBuffer.addUniform("vLightmapInfos", 2);
+            this._uniformBuffer.addUniform("vSpecularInfos", 2);
+            this._uniformBuffer.addUniform("vBumpInfos", 3);
+
+            this._uniformBuffer.addUniform("diffuseMatrix", 16);
+            this._uniformBuffer.addUniform("ambientMatrix", 16);
+            this._uniformBuffer.addUniform("opacityMatrix", 16);
+            this._uniformBuffer.addUniform("reflectionMatrix", 16);
+            this._uniformBuffer.addUniform("emissiveMatrix", 16);
+            this._uniformBuffer.addUniform("lightmapMatrix", 16);
+            this._uniformBuffer.addUniform("specularMatrix", 16);
+            this._uniformBuffer.addUniform("bumpMatrix", 16);
+            this._uniformBuffer.addUniform("refractionMatrix", 16);
+            this._uniformBuffer.addUniform("vRefractionInfos", 4);
+            this._uniformBuffer.addUniform("vSpecularColor", 4);
+            this._uniformBuffer.addUniform("vEmissiveColor", 3);
+            this._uniformBuffer.addUniform("vDiffuseColor", 4);
+            this._uniformBuffer.addUniform("pointSize", 1);
+
+            this._uniformBuffer.create();
+        }
+
         public unbind(): void {
             if (this._activeEffect) {
                 if (this._reflectionTexture && this._reflectionTexture.isRenderTarget) {
@@ -771,58 +820,119 @@ module BABYLON {
 
             // Bones
             MaterialHelper.BindBonesParameters(mesh, effect);
-
             if (this._mustRebind(scene, effect)) {
-                effect.setMatrix("viewProjection", scene.getTransformMatrix());
+                this._uniformBuffer.bindToEffect(effect, "Material");
+                
+                this.bindViewProjection(effect);
+                if (!this._uniformBuffer.useUbo || !this.isFrozen || !this._uniformBuffer.isSync) {
+
+                    if (StandardMaterial.FresnelEnabled && defines.FRESNEL) {
+                        // Fresnel
+                        if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
+                            this._uniformBuffer.updateColor4("diffuseLeftColor", this.diffuseFresnelParameters.leftColor, this.diffuseFresnelParameters.power);
+                            this._uniformBuffer.updateColor4("diffuseRightColor", this.diffuseFresnelParameters.rightColor, this.diffuseFresnelParameters.bias);
+                        }
 
-                if (StandardMaterial.FresnelEnabled && defines.FRESNEL) {
-                    // Fresnel
-                    if (this.diffuseFresnelParameters && this.diffuseFresnelParameters.isEnabled) {
-                        effect.setColor4("diffuseLeftColor", this.diffuseFresnelParameters.leftColor, this.diffuseFresnelParameters.power);
-                        effect.setColor4("diffuseRightColor", this.diffuseFresnelParameters.rightColor, this.diffuseFresnelParameters.bias);
-                    }
+                        if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
+                            this._uniformBuffer.updateColor4("opacityParts", new Color3(this.opacityFresnelParameters.leftColor.toLuminance(), this.opacityFresnelParameters.rightColor.toLuminance(), this.opacityFresnelParameters.bias), this.opacityFresnelParameters.power);
+                        }
+
+                        if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
+                            this._uniformBuffer.updateColor4("reflectionLeftColor", this.reflectionFresnelParameters.leftColor, this.reflectionFresnelParameters.power);
+                            this._uniformBuffer.updateColor4("reflectionRightColor", this.reflectionFresnelParameters.rightColor, this.reflectionFresnelParameters.bias);
+                        }
+
+                        if (this.refractionFresnelParameters && this.refractionFresnelParameters.isEnabled) {
+                            this._uniformBuffer.updateColor4("refractionLeftColor", this.refractionFresnelParameters.leftColor, this.refractionFresnelParameters.power);
+                            this._uniformBuffer.updateColor4("refractionRightColor", this.refractionFresnelParameters.rightColor, this.refractionFresnelParameters.bias);
+                        }
 
-                    if (this.opacityFresnelParameters && this.opacityFresnelParameters.isEnabled) {
-                        effect.setColor4("opacityParts", new Color3(this.opacityFresnelParameters.leftColor.toLuminance(), this.opacityFresnelParameters.rightColor.toLuminance(), this.opacityFresnelParameters.bias), this.opacityFresnelParameters.power);
+                        if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
+                            this._uniformBuffer.updateColor4("emissiveLeftColor", this.emissiveFresnelParameters.leftColor, this.emissiveFresnelParameters.power);
+                            this._uniformBuffer.updateColor4("emissiveRightColor", this.emissiveFresnelParameters.rightColor, this.emissiveFresnelParameters.bias);
+                        }
                     }
 
-                    if (this.reflectionFresnelParameters && this.reflectionFresnelParameters.isEnabled) {
-                        effect.setColor4("reflectionLeftColor", this.reflectionFresnelParameters.leftColor, this.reflectionFresnelParameters.power);
-                        effect.setColor4("reflectionRightColor", this.reflectionFresnelParameters.rightColor, this.reflectionFresnelParameters.bias);
+                    // Textures     
+                    if (scene.texturesEnabled) {
+                        if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                            this._uniformBuffer.updateFloat2("vDiffuseInfos", this._diffuseTexture.coordinatesIndex, this._diffuseTexture.level);
+                            this._uniformBuffer.updateMatrix("diffuseMatrix", this._diffuseTexture.getTextureMatrix());
+                        }
+
+                        if (this._ambientTexture && StandardMaterial.AmbientTextureEnabled) {
+                            this._uniformBuffer.updateFloat2("vAmbientInfos", this._ambientTexture.coordinatesIndex, this._ambientTexture.level);
+                            this._uniformBuffer.updateMatrix("ambientMatrix", this._ambientTexture.getTextureMatrix());
+                        }
+
+                        if (this._opacityTexture && StandardMaterial.OpacityTextureEnabled) {
+                            this._uniformBuffer.updateFloat2("vOpacityInfos", this._opacityTexture.coordinatesIndex, this._opacityTexture.level);
+                            this._uniformBuffer.updateMatrix("opacityMatrix", this._opacityTexture.getTextureMatrix());
+                        }
+
+                        if (this._reflectionTexture && StandardMaterial.ReflectionTextureEnabled) {
+                            this._uniformBuffer.updateFloat2("vReflectionInfos", this._reflectionTexture.level, this.roughness);
+                            this._uniformBuffer.updateMatrix("reflectionMatrix", this._reflectionTexture.getReflectionTextureMatrix());
+                        }
+
+                        if (this._emissiveTexture && StandardMaterial.EmissiveTextureEnabled) {
+                            this._uniformBuffer.updateFloat2("vEmissiveInfos", this._emissiveTexture.coordinatesIndex, this._emissiveTexture.level);
+                            this._uniformBuffer.updateMatrix("emissiveMatrix", this._emissiveTexture.getTextureMatrix());
+                        }
+
+                        if (this._lightmapTexture && StandardMaterial.LightmapTextureEnabled) {
+                            this._uniformBuffer.updateFloat2("vLightmapInfos", this._lightmapTexture.coordinatesIndex, this._lightmapTexture.level);
+                            this._uniformBuffer.updateMatrix("lightmapMatrix", this._lightmapTexture.getTextureMatrix());
+                        }
+
+                        if (this._specularTexture && StandardMaterial.SpecularTextureEnabled) {
+                            this._uniformBuffer.updateFloat2("vSpecularInfos", this._specularTexture.coordinatesIndex, this._specularTexture.level);
+                            this._uniformBuffer.updateMatrix("specularMatrix", this._specularTexture.getTextureMatrix());
+                        }
+
+                        if (this._bumpTexture && scene.getEngine().getCaps().standardDerivatives && StandardMaterial.BumpTextureEnabled) {
+                            this._uniformBuffer.updateFloat3("vBumpInfos", this._bumpTexture.coordinatesIndex, 1.0 / this._bumpTexture.level, this.parallaxScaleBias);
+                            this._uniformBuffer.updateMatrix("bumpMatrix", this._bumpTexture.getTextureMatrix());
+                        }
+
+                        if (this._refractionTexture && StandardMaterial.RefractionTextureEnabled) {
+                            var depth = 1.0;
+                            if (!this._refractionTexture.isCube) {
+                                this._uniformBuffer.updateMatrix("refractionMatrix", this._refractionTexture.getReflectionTextureMatrix());
+
+                                if ((<any>this._refractionTexture).depth) {
+                                    depth = (<any>this._refractionTexture).depth;
+                                }
+                            }
+                            this._uniformBuffer.updateFloat4("vRefractionInfos", this._refractionTexture.level, this.indexOfRefraction, depth, this.invertRefractionY ? -1 : 1);
+                        }                    
                     }
 
-                    if (this.refractionFresnelParameters && this.refractionFresnelParameters.isEnabled) {
-                        effect.setColor4("refractionLeftColor", this.refractionFresnelParameters.leftColor, this.refractionFresnelParameters.power);
-                        effect.setColor4("refractionRightColor", this.refractionFresnelParameters.rightColor, this.refractionFresnelParameters.bias);
+                    // Point size
+                    if (this.pointsCloud) {
+                        this._uniformBuffer.updateFloat("pointSize", this.pointSize);
                     }
 
-                    if (this.emissiveFresnelParameters && this.emissiveFresnelParameters.isEnabled) {
-                        effect.setColor4("emissiveLeftColor", this.emissiveFresnelParameters.leftColor, this.emissiveFresnelParameters.power);
-                        effect.setColor4("emissiveRightColor", this.emissiveFresnelParameters.rightColor, this.emissiveFresnelParameters.bias);
+                    if (defines.SPECULARTERM) {
+                        this._uniformBuffer.updateColor4("vSpecularColor", this.specularColor, this.specularPower);
                     }
+                    this._uniformBuffer.updateColor3("vEmissiveColor", this.emissiveColor);
+                    // Diffuse
+                    this._uniformBuffer.updateColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
                 }
-
+                
                 // Textures     
                 if (scene.texturesEnabled) {
                     if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
                         effect.setTexture("diffuseSampler", this._diffuseTexture);
-
-                        effect.setFloat2("vDiffuseInfos", this._diffuseTexture.coordinatesIndex, this._diffuseTexture.level);
-                        effect.setMatrix("diffuseMatrix", this._diffuseTexture.getTextureMatrix());
                     }
 
                     if (this._ambientTexture && StandardMaterial.AmbientTextureEnabled) {
                         effect.setTexture("ambientSampler", this._ambientTexture);
-
-                        effect.setFloat2("vAmbientInfos", this._ambientTexture.coordinatesIndex, this._ambientTexture.level);
-                        effect.setMatrix("ambientMatrix", this._ambientTexture.getTextureMatrix());
                     }
 
                     if (this._opacityTexture && StandardMaterial.OpacityTextureEnabled) {
                         effect.setTexture("opacitySampler", this._opacityTexture);
-
-                        effect.setFloat2("vOpacityInfos", this._opacityTexture.coordinatesIndex, this._opacityTexture.level);
-                        effect.setMatrix("opacityMatrix", this._opacityTexture.getTextureMatrix());
                     }
 
                     if (this._reflectionTexture && StandardMaterial.ReflectionTextureEnabled) {
@@ -831,37 +941,22 @@ module BABYLON {
                         } else {
                             effect.setTexture("reflection2DSampler", this._reflectionTexture);
                         }
-
-                        effect.setMatrix("reflectionMatrix", this._reflectionTexture.getReflectionTextureMatrix());
-                        effect.setFloat2("vReflectionInfos", this._reflectionTexture.level, this.roughness);
                     }
 
                     if (this._emissiveTexture && StandardMaterial.EmissiveTextureEnabled) {
                         effect.setTexture("emissiveSampler", this._emissiveTexture);
-
-                        effect.setFloat2("vEmissiveInfos", this._emissiveTexture.coordinatesIndex, this._emissiveTexture.level);
-                        effect.setMatrix("emissiveMatrix", this._emissiveTexture.getTextureMatrix());
                     }
 
                     if (this._lightmapTexture && StandardMaterial.LightmapTextureEnabled) {
                         effect.setTexture("lightmapSampler", this._lightmapTexture);
-
-                        effect.setFloat2("vLightmapInfos", this._lightmapTexture.coordinatesIndex, this._lightmapTexture.level);
-                        effect.setMatrix("lightmapMatrix", this._lightmapTexture.getTextureMatrix());
                     }
 
                     if (this._specularTexture && StandardMaterial.SpecularTextureEnabled) {
                         effect.setTexture("specularSampler", this._specularTexture);
-
-                        effect.setFloat2("vSpecularInfos", this._specularTexture.coordinatesIndex, this._specularTexture.level);
-                        effect.setMatrix("specularMatrix", this._specularTexture.getTextureMatrix());
                     }
 
                     if (this._bumpTexture && scene.getEngine().getCaps().standardDerivatives && StandardMaterial.BumpTextureEnabled) {
                         effect.setTexture("bumpSampler", this._bumpTexture);
-
-                        effect.setFloat3("vBumpInfos", this._bumpTexture.coordinatesIndex, 1.0 / this._bumpTexture.level, this.parallaxScaleBias);
-                        effect.setMatrix("bumpMatrix", this._bumpTexture.getTextureMatrix());
                     }
 
                     if (this._refractionTexture && StandardMaterial.RefractionTextureEnabled) {
@@ -870,13 +965,7 @@ module BABYLON {
                             effect.setTexture("refractionCubeSampler", this._refractionTexture);
                         } else {
                             effect.setTexture("refraction2DSampler", this._refractionTexture);
-                            effect.setMatrix("refractionMatrix", this._refractionTexture.getReflectionTextureMatrix());
-
-                            if ((<any>this._refractionTexture).depth) {
-                                depth = (<any>this._refractionTexture).depth;
-                            }
                         }
-                        effect.setFloat4("vRefractionInfos", this._refractionTexture.level, this.indexOfRefraction, depth, this.invertRefractionY ? -1 : 1);
                     }
                     
                     if (this._cameraColorGradingTexture && StandardMaterial.ColorGradingTextureEnabled) {
@@ -887,37 +976,24 @@ module BABYLON {
                 // Clip plane
                 MaterialHelper.BindClipPlane(effect, scene);
 
-                // Point size
-                if (this.pointsCloud) {
-                    effect.setFloat("pointSize", this.pointSize);
-                }
-
                 // Colors
                 scene.ambientColor.multiplyToRef(this.ambientColor, this._globalAmbientColor);
 
                 effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);
                 effect.setColor3("vAmbientColor", this._globalAmbientColor);
-
-                if (defines.SPECULARTERM) {
-                    effect.setColor4("vSpecularColor", this.specularColor, this.specularPower);
-                }
-                effect.setColor3("vEmissiveColor", this.emissiveColor);
             }
 
             if (this._mustRebind(scene, effect) || !this.isFrozen) {
-                // Diffuse
-                effect.setColor4("vDiffuseColor", this.diffuseColor, this.alpha * mesh.visibility);
-
                 // Lights
-                if (scene.lightsEnabled && !this.disableLighting) {
+                if (scene.lightsEnabled && !this._disableLighting) {
                     MaterialHelper.BindLights(scene, mesh, effect, defines, this._maxSimultaneousLights);
                 }
 
                 // View
                 if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE || this._reflectionTexture || this._refractionTexture) {
-                    effect.setMatrix("view", scene.getViewMatrix());
+                    this.bindView(effect);
                 }
-
+                
                 // Fog
                 MaterialHelper.BindFogParameters(scene, mesh, effect);
 
@@ -930,11 +1006,13 @@ module BABYLON {
                 MaterialHelper.BindLogDepth(defines, effect, scene);
 
                 // Color Curves
-                if (this.cameraColorCurves) {
-                    ColorCurves.Bind(this.cameraColorCurves, effect);
+                if (this._cameraColorCurves) {
+                    ColorCurves.Bind(this._cameraColorCurves, effect);
                 }
+
             }
 
+            this._uniformBuffer.update();
             this._afterBind(mesh, this._activeEffect);
         }
 

+ 611 - 0
src/Materials/babylon.uniformBuffer.ts

@@ -0,0 +1,611 @@
+module BABYLON {
+
+    export class UniformBuffer {
+        private _engine: Engine;
+        private _buffer: WebGLBuffer;
+        private _data: number[];
+        private _bufferData: Float32Array;
+        private _dynamic: boolean;
+        private _uniformName: string;
+        private _uniformLocations: { [key:string]:number; };
+        private _uniformSizes: { [key:string]:number; };
+        private _uniformLocationPointer: number;
+        private _needSync: boolean;
+        private _cache: Float32Array;
+        private _noUBO: boolean;
+        private _currentEffect: Effect;
+
+        // Pool for avoiding memory leaks
+        private static _MAX_UNIFORM_SIZE = 256;
+        private static _tempBuffer = new Float32Array(UniformBuffer._MAX_UNIFORM_SIZE);
+
+        /**
+         * Wrapper for updateUniform.
+         * @method updateMatrix3x3 
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {Float32Array} matrix
+         */
+        public updateMatrix3x3: (name: string, matrix: Float32Array) => void;
+
+        /**
+         * Wrapper for updateUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {Float32Array} matrix
+         */
+        public updateMatrix2x2: (name: string, matrix: Float32Array) => void;
+
+        /**
+         * Wrapper for updateUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {number} x
+         */
+        public updateFloat: (name: string, x: number) => void;
+
+        /**
+         * Wrapper for updateUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {number} x
+         * @param {number} y
+         */
+        public updateFloat2: (name: string, x: number, y: number) => void;
+
+        /**
+         * Wrapper for updateUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {number} x
+         * @param {number} y
+         * @param {number} z
+         * @param {string} [suffix] Suffix to add to the uniform name.
+         */
+        public updateFloat3: (name: string, x: number, y: number, z: number, suffix?: string) => void;
+
+        /**
+         * Wrapper for updateUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {number} x
+         * @param {number} y
+         * @param {number} z
+         * @param {number} w
+         * @param {string} [suffix] Suffix to add to the uniform name.
+         */
+        public updateFloat4: (name: string, x: number, y: number, z: number, w: number, suffix?: string) => void;
+
+        /**
+         * Wrapper for updateUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {Matrix} A 4x4 matrix.
+         */
+        public updateMatrix: (name: string, mat: Matrix) => void;
+
+        /**
+         * Wrapper for updateUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {Vector3} vector
+         */
+        public updateVector3: (name: string, vector: Vector3) => void;
+
+        /**
+         * Wrapper for updateUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {Vector4} vector
+         */
+        public updateVector4: (name: string, vector: Vector4) => void;
+
+        /**
+         * Wrapper for updateUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {Color3} color
+         * @param {string} [suffix] Suffix to add to the uniform name.
+         */
+        public updateColor3: (name: string, color: Color3, suffix?: string) => void;
+
+        /**
+         * Wrapper for updateUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {Color3} color
+         * @param {number} alpha
+         * @param {string} [suffix] Suffix to add to the uniform name.
+         */
+        public updateColor4: (name: string, color: Color3, alpha: number, suffix?: string) => void;
+
+        /**
+         * Uniform buffer objects.
+         * 
+         * Handles blocks of uniform on the GPU.
+         *
+         * If WebGL 2 is not available, this class falls back on traditionnal setUniformXXX calls.
+         *
+         * For more information, please refer to : 
+         * https://www.khronos.org/opengl/wiki/Uniform_Buffer_Object
+         */
+        constructor(engine: Engine, data?: number[], dynamic?: boolean) {
+            this._engine = engine;
+            this._noUBO = engine.webGLVersion === 1;
+            this._dynamic = dynamic;
+
+            this._data = data || [];
+
+            this._uniformLocations = {};
+            this._uniformSizes = {};
+            this._uniformLocationPointer = 0;
+            this._needSync = false;
+
+            if (this._noUBO) {
+                this.updateMatrix3x3 = this._updateMatrix3x3ForEffect;
+                this.updateMatrix2x2 = this._updateMatrix2x2ForEffect;
+                this.updateFloat = this._updateFloatForEffect;
+                this.updateFloat2 = this._updateFloat2ForEffect;
+                this.updateFloat3 = this._updateFloat3ForEffect;
+                this.updateFloat4 = this._updateFloat4ForEffect;
+                this.updateMatrix = this._updateMatrixForEffect;
+                this.updateVector3 = this._updateVector3ForEffect;
+                this.updateVector4 = this._updateVector4ForEffect;
+                this.updateColor3 = this._updateColor3ForEffect;
+                this.updateColor4 = this._updateColor4ForEffect;
+            } else {
+                this.updateMatrix3x3 = this._updateMatrix3x3ForUniform;
+                this.updateMatrix2x2 = this._updateMatrix2x2ForUniform;
+                this.updateFloat = this._updateFloatForUniform;
+                this.updateFloat2 = this._updateFloat2ForUniform;
+                this.updateFloat3 = this._updateFloat3ForUniform;
+                this.updateFloat4 = this._updateFloat4ForUniform;
+                this.updateMatrix = this._updateMatrixForUniform;
+                this.updateVector3 = this._updateVector3ForUniform;
+                this.updateVector4 = this._updateVector4ForUniform;
+                this.updateColor3 = this._updateColor3ForUniform;
+                this.updateColor4 = this._updateColor4ForUniform;
+            }
+
+        }
+
+        // Properties
+        /**
+         * Indicates if the buffer is using the WebGL2 UBO implementation,
+         * or just falling back on setUniformXXX calls.
+         */
+        public get useUbo(): boolean {
+            return !this._noUBO;
+        }
+        
+        /**
+         * Indicates if the WebGL underlying uniform buffer is in sync
+         * with the javascript cache data.
+         */
+        public get isSync(): boolean {
+            return !this._needSync;
+        }
+
+        /**
+         * Indicates if the WebGL underlying uniform buffer is dynamic.
+         * Also, a dynamic UniformBuffer will disable cache verification and always 
+         * update the underlying WebGL uniform buffer to the GPU.
+         */
+        public isDynamic(): boolean {
+            return this._dynamic;
+        }
+
+        /**
+         * The data cache on JS side.
+         */
+        public getData(): Float32Array {
+            return this._bufferData;
+        }
+
+        /**
+         * The underlying WebGL Uniform buffer.
+         */
+        public getBuffer(): WebGLBuffer {
+            return this._buffer;
+        }
+
+        /**
+         * std140 layout specifies how to align data within an UBO structure.
+         * See https://khronos.org/registry/OpenGL/specs/gl/glspec45.core.pdf#page=159
+         * for specs.
+         */
+        private _fillAlignment(size: number) {
+            // This code has been simplified because we only use floats, vectors of 1, 2, 3, 4 components
+            // and 4x4 matrices
+            // TODO : change if other types are used
+
+            var alignment;
+            if (size <= 2) {
+                alignment = size;
+            } else {
+                alignment = 4;
+            }
+
+            if ((this._uniformLocationPointer % alignment) !== 0) {
+                var oldPointer = this._uniformLocationPointer;
+                this._uniformLocationPointer += alignment - (this._uniformLocationPointer % alignment);
+                var diff = this._uniformLocationPointer - oldPointer;
+
+                for (var i = 0; i < diff; i++) {
+                      this._data.push(0); 
+                }
+            }
+        }
+
+        /**
+         * Adds an uniform in the buffer.
+         * Warning : the subsequents calls of this function must be in the same order as declared in the shader
+         * for the layout to be correct !
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {number|number[]} size Data size, or data directly.
+         */
+        public addUniform(name: string, size: number | number[]) {
+            if (this._noUBO) {
+                return;
+            }
+
+            if (this._uniformLocations[name] !== undefined) {
+                // Already existing uniform
+                return;
+            }
+            // This function must be called in the order of the shader layout !
+            // size can be the size of the uniform, or data directly
+            var data;
+            if (size instanceof Array) {
+                data = size;
+                size = data.length;
+            } else {
+                size = <number>size;
+                data = [];
+
+                // Fill with zeros
+                for (var i = 0; i < size; i++) {
+                    data.push(0);
+                }
+            }
+
+
+            this._fillAlignment(<number>size);
+            this._uniformSizes[name] = <number>size;
+            this._uniformLocations[name] = this._uniformLocationPointer;
+            this._uniformLocationPointer += <number>size;
+
+
+            for (var i = 0; i < size; i++) {
+                this._data.push(data[i]);
+            }
+
+            this._needSync = true;
+        }
+
+        /**
+         * Wrapper for addUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {Matrix} mat A 4x4 matrix.
+         */
+        public addMatrix(name: string, mat: Matrix) {
+            this.addUniform(name, Array.prototype.slice.call(mat.toArray()));
+        }
+
+        /**
+         * Wrapper for addUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {number} x
+         * @param {number} y
+         */
+        public addFloat2(name: string, x: number, y: number) {
+            var temp = [x, y];
+            this.addUniform(name, temp);
+        }
+
+        /**
+         * Wrapper for addUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {number} x
+         * @param {number} y
+         * @param {number} z
+         */
+        public addFloat3(name: string, x: number, y: number, z: number) {
+            var temp = [x, y, z];
+            this.addUniform(name, temp);
+        }
+
+        /**
+         * Wrapper for addUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {Color3} color
+         */
+        public addColor3(name: string, color: Color3) {
+            var temp = [];
+            color.toArray(temp);
+            this.addUniform(name, temp);
+        }
+
+        /**
+         * Wrapper for addUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {Color3} color
+         * @param {number} alpha
+         */
+        public addColor4(name: string, color: Color3, alpha: number) {
+            var temp = [];
+            color.toArray(temp);
+            temp.push(alpha);
+            this.addUniform(name, temp);
+        }
+
+        /**
+         * Wrapper for addUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         * @param {Vector3} vector
+         */
+        public addVector3(name: string, vector: Vector3) {
+            var temp = [];
+            vector.toArray(temp);
+            this.addUniform(name, temp);
+        }
+
+        /**
+         * Wrapper for addUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         */
+        public addMatrix3x3(name: string) {
+            this.addUniform(name, 12);
+        }
+
+        /**
+         * Wrapper for addUniform.
+         * @param {string} name Name of the uniform, as used in the uniform block in the shader.
+         */
+        public addMatrix2x2(name: string) {
+            this.addUniform(name, 8);
+        }
+
+        /**
+         * Effectively creates the WebGL Uniform Buffer, once layout is completed with `addUniform`.
+         */
+        public create(): void {
+            if (this._noUBO) {
+                return;
+            }
+            if (this._buffer) {
+                return; // nothing to do
+            }
+
+            this._bufferData = new Float32Array(this._data);
+
+            if (this._dynamic) {
+                this._buffer = this._engine.createDynamicUniformBuffer(this._bufferData);
+            } else {
+                this._buffer = this._engine.createUniformBuffer(this._bufferData);
+            }
+
+            this._needSync = true;
+        } 
+
+        /**
+         * Updates the WebGL Uniform Buffer on the GPU.
+         * If the `dynamic` flag is set to true, no cache comparison is done.
+         * Otherwise, the buffer will be updated only if the cache differs.
+         */
+        public update(): void {
+            if (!this._buffer) {
+                this.create();
+                return;
+            }
+
+            if (!this._dynamic && !this._needSync) {
+                return;
+            }
+
+            this._engine.updateUniformBuffer(this._buffer, this._bufferData);
+
+            this._needSync = false;
+        }
+
+        /**
+         * Updates the value of an uniform. The `update` method must be called afterwards to make it effective in the GPU.
+         * @param {string} uniformName Name of the uniform, as used in the uniform block in the shader.
+         * @param {number[]|Float32Array} data Flattened data
+         * @param {number} size Size of the data.
+         */
+        public updateUniform(uniformName: string, data: number[] | Float32Array, size: number) {
+
+            var location = this._uniformLocations[uniformName];
+            if (location === undefined) {
+                if (this._buffer) {
+                    // Cannot add an uniform if the buffer is already created
+                    Tools.Error("Cannot add an uniform after UBO has been created.");
+                    return;
+                }
+                this.addUniform(uniformName, size);
+                location = this._uniformLocations[uniformName];
+            }
+
+            if (!this._buffer) {
+                this.create();
+            }
+
+            if (!this._dynamic) {
+                // Cache for static uniform buffers
+                var changed = false;
+                for (var i = 0; i < size; i++) {
+                    if (this._bufferData[location + i] !== data[i]) {
+                       changed = true;
+                        this._bufferData[location + i] = data[i];
+                    }
+                }
+
+                this._needSync = this._needSync || changed;
+            } else {
+                // No cache for dynamic
+                for (var i = 0; i < size; i++) {
+                    this._bufferData[location + i] = data[i];
+                }
+            }
+        }
+
+        // Update methods
+
+        private _updateMatrix3x3ForUniform(name: string, matrix: Float32Array): void {
+            // To match std140, matrix must be realigned
+            for (var i = 0; i < 3; i++) {
+                UniformBuffer._tempBuffer[i * 4] = matrix[i * 3];
+                UniformBuffer._tempBuffer[i * 4 + 1] = matrix[i * 3 + 1];
+                UniformBuffer._tempBuffer[i * 4 + 2] = matrix[i * 3 + 2];
+                UniformBuffer._tempBuffer[i * 4 + 3] = 0.0;
+            }
+
+            this.updateUniform(name, UniformBuffer._tempBuffer, 12);
+        }
+
+        private _updateMatrix3x3ForEffect(name: string, matrix: Float32Array): void {
+            this._currentEffect.setMatrix3x3(name, matrix);
+        }
+
+        private _updateMatrix2x2ForEffect(name: string, matrix: Float32Array): void {
+            this._currentEffect.setMatrix2x2(name, matrix);
+        }
+
+        private _updateMatrix2x2ForUniform(name: string, matrix: Float32Array): void {
+            // To match std140, matrix must be realigned
+            for (var i = 0; i < 2; i++) {
+                UniformBuffer._tempBuffer[i * 4] = matrix[i * 2];
+                UniformBuffer._tempBuffer[i * 4 + 1] = matrix[i * 2 + 1];
+                UniformBuffer._tempBuffer[i * 4 + 2] = 0.0;
+                UniformBuffer._tempBuffer[i * 4 + 3] = 0.0;
+            }
+
+            this.updateUniform(name, UniformBuffer._tempBuffer, 8);
+        }
+
+        private _updateFloatForEffect(name: string, x: number) {
+            this._currentEffect.setFloat(name, x);
+        }
+
+        private _updateFloatForUniform(name: string, x: number) {
+            UniformBuffer._tempBuffer[0] = x;
+            this.updateUniform(name, UniformBuffer._tempBuffer, 1);
+        }
+
+        private _updateFloat2ForEffect(name: string, x: number, y: number) {
+            this._currentEffect.setFloat2(name, x, y);
+        }
+
+        private _updateFloat2ForUniform(name: string, x: number, y: number) {
+            UniformBuffer._tempBuffer[0] = x;
+            UniformBuffer._tempBuffer[1] = y;
+            this.updateUniform(name, UniformBuffer._tempBuffer, 2);
+        }        
+
+        private _updateFloat3ForEffect(name: string, x: number, y: number, z: number, suffix = "") {
+            this._currentEffect.setFloat3(name + suffix, x, y, z);
+        }
+
+        private _updateFloat3ForUniform(name: string, x: number, y: number, z: number, suffix = "") {
+            UniformBuffer._tempBuffer[0] = x;
+            UniformBuffer._tempBuffer[1] = y;
+            UniformBuffer._tempBuffer[2] = z;
+            this.updateUniform(name, UniformBuffer._tempBuffer, 3);
+
+        }
+
+        private _updateFloat4ForEffect(name: string, x: number, y: number, z: number, w: number, suffix = "") {
+            this._currentEffect.setFloat4(name + suffix, x, y, z, w);
+        }
+
+        private _updateFloat4ForUniform(name: string, x: number, y: number, z: number, w: number, suffix = "") {
+            UniformBuffer._tempBuffer[0] = x;
+            UniformBuffer._tempBuffer[1] = y;
+            UniformBuffer._tempBuffer[2] = z;
+            UniformBuffer._tempBuffer[3] = w;
+            this.updateUniform(name, UniformBuffer._tempBuffer, 4);
+        }
+
+        private _updateMatrixForEffect(name: string, mat: Matrix) {
+            this._currentEffect.setMatrix(name, mat);
+        }
+
+        private _updateMatrixForUniform(name: string, mat: Matrix) {
+            this.updateUniform(name, mat.toArray(), 16);
+        }
+
+        private _updateVector3ForEffect(name: string, vector: Vector3) {
+            this._currentEffect.setVector3(name, vector);
+        }
+
+        private _updateVector3ForUniform(name: string, vector: Vector3) {
+            vector.toArray(UniformBuffer._tempBuffer);
+            this.updateUniform(name, UniformBuffer._tempBuffer, 3);
+        }
+
+        private _updateVector4ForEffect(name: string, vector: Vector4) {
+            this._currentEffect.setVector4(name, vector);
+        }
+
+        private _updateVector4ForUniform(name: string, vector: Vector4) {
+            vector.toArray(UniformBuffer._tempBuffer);
+            this.updateUniform(name, UniformBuffer._tempBuffer, 4);
+        }
+
+        private _updateColor3ForEffect(name: string, color: Color3, suffix = "") {
+            this._currentEffect.setColor3(name + suffix, color);
+        }
+
+        private _updateColor3ForUniform(name: string, color: Color3, suffix = "") {
+            color.toArray(UniformBuffer._tempBuffer);
+            this.updateUniform(name, UniformBuffer._tempBuffer, 3);
+        }
+
+        private _updateColor4ForEffect(name: string, color: Color3, alpha: number, suffix = "") {
+            this._currentEffect.setColor4(name + suffix, color, alpha);
+        }
+
+        private _updateColor4ForUniform(name: string, color: Color3, alpha: number, suffix = "") {
+            color.toArray(UniformBuffer._tempBuffer);
+            UniformBuffer._tempBuffer[3] = alpha;
+            this.updateUniform(name, UniformBuffer._tempBuffer, 4);
+        }
+
+        /**
+         * Sets a sampler uniform on the effect.
+         * @param {string} name Name of the sampler.
+         * @param {Texture} texture
+         */
+        public setTexture(name: string, texture: BaseTexture) {
+            this._currentEffect.setTexture(name, texture);
+        }
+
+        /**
+         * Directly updates the value of the uniform in the cache AND on the GPU.
+         * @param {string} uniformName Name of the uniform, as used in the uniform block in the shader.
+         * @param {number[]|Float32Array} data Flattened data
+         */
+        public updateUniformDirectly(uniformName: string, data: number[] | Float32Array) {
+            this.updateUniform(uniformName, data, data.length);
+
+            this.update();
+        }
+
+        /**
+         * Binds this uniform buffer to an effect.
+         * @param {Effect} effect
+         * @param {string} name Name of the uniform block in the shader.
+         */
+        public bindToEffect(effect: Effect, name: string): void {
+            this._currentEffect = effect;
+
+            if (this._noUBO) {
+                return;
+            }
+            
+            effect.bindUniformBuffer(this._buffer, name);
+        }
+
+        /**
+         * Disposes the uniform buffer.
+         */
+        public dispose(): void {
+            if (!this._buffer) {
+                return;
+            }
+            if (this._engine._releaseBuffer(this._buffer)) {
+                this._buffer = null;
+            }
+        }
+    }
+} 

+ 2 - 2
src/Math/babylon.math.ts

@@ -88,7 +88,7 @@
          * Stores in the passed array from the passed starting index the red, green, blue values as successive elements.  
          * Returns the Color3.  
          */
-        public toArray(array: number[], index?: number): Color3 {
+        public toArray(array: number[] | Float32Array, index?: number): Color3 {
             if (index === undefined) {
                 index = 0;
             }
@@ -1834,7 +1834,7 @@
          * Populates the passed array from the passed index with the Vector4 coordinates.  
          * Returns the Vector4.  
          */
-        public toArray(array: number[], index?: number): Vector4 {
+        public toArray(array: number[] | Float32Array, index?: number): Vector4 {
             if (index === undefined) {
                 index = 0;
             }

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

@@ -1,6 +1,5 @@
 #ifdef BUMP
 	varying vec2 vBumpUV;
-	uniform vec3 vBumpInfos;
 	uniform sampler2D bumpSampler;
 #if defined(TANGENT) && defined(NORMAL) 
 	varying mat3 vTBN;

+ 84 - 0
src/Shaders/ShadersInclude/defaultFragmentDeclaration.fx

@@ -0,0 +1,84 @@
+uniform vec4 vDiffuseColor;
+#ifdef SPECULARTERM
+uniform vec4 vSpecularColor;
+#endif
+uniform vec3 vEmissiveColor;
+
+// Samplers
+#ifdef DIFFUSE
+uniform vec2 vDiffuseInfos;
+#endif
+
+#ifdef AMBIENT
+uniform vec2 vAmbientInfos;
+#endif
+
+#ifdef OPACITY	
+uniform vec2 vOpacityInfos;
+#endif
+
+#ifdef EMISSIVE
+uniform vec2 vEmissiveInfos;
+#endif
+
+#ifdef LIGHTMAP
+uniform vec2 vLightmapInfos;
+#endif
+
+#ifdef BUMP
+uniform vec3 vBumpInfos;
+#endif
+
+#if defined(REFLECTIONMAP_SPHERICAL) || defined(REFLECTIONMAP_PROJECTION) || defined(REFRACTION)
+uniform mat4 view;
+#endif
+
+#ifdef REFRACTION
+uniform vec4 vRefractionInfos;
+
+#ifndef REFRACTIONMAP_3D
+uniform mat4 refractionMatrix;
+#endif
+
+#ifdef REFRACTIONFRESNEL
+uniform vec4 refractionLeftColor;
+uniform vec4 refractionRightColor;
+#endif
+#endif
+
+#if defined(SPECULAR) && defined(SPECULARTERM)
+uniform vec2 vSpecularInfos;
+#endif
+
+#ifdef DIFFUSEFRESNEL
+uniform vec4 diffuseLeftColor;
+uniform vec4 diffuseRightColor;
+#endif
+
+#ifdef OPACITYFRESNEL
+uniform vec4 opacityParts;
+#endif
+
+#ifdef EMISSIVEFRESNEL
+uniform vec4 emissiveLeftColor;
+uniform vec4 emissiveRightColor;
+#endif
+
+// Reflection
+#ifdef REFLECTION
+uniform vec2 vReflectionInfos;
+
+#ifdef REFLECTIONMAP_SKYBOX
+#else
+
+#if defined(REFLECTIONMAP_PLANAR) || defined(REFLECTIONMAP_CUBIC) || defined(REFLECTIONMAP_PROJECTION)
+uniform mat4 reflectionMatrix;
+#endif
+#endif
+
+#ifdef REFLECTIONFRESNEL
+uniform vec4 reflectionLeftColor;
+uniform vec4 reflectionRightColor;
+#endif
+
+#endif

+ 41 - 0
src/Shaders/ShadersInclude/defaultUboDeclaration.fx

@@ -0,0 +1,41 @@
+layout(std140, column_major) uniform;
+
+uniform Material
+{
+	vec4 diffuseLeftColor;
+	vec4 diffuseRightColor;
+	vec4 opacityParts;
+	vec4 reflectionLeftColor;
+	vec4 reflectionRightColor;
+	vec4 refractionLeftColor;
+	vec4 refractionRightColor;
+	vec4 emissiveLeftColor; 
+	vec4 emissiveRightColor;
+	vec2 vDiffuseInfos;
+	vec2 vAmbientInfos;
+	vec2 vOpacityInfos;
+	vec2 vReflectionInfos;
+	vec2 vEmissiveInfos;
+	vec2 vLightmapInfos;
+	vec2 vSpecularInfos;
+	vec3 vBumpInfos;
+	mat4 diffuseMatrix;
+	mat4 ambientMatrix;
+	mat4 opacityMatrix;
+	mat4 reflectionMatrix;
+	mat4 emissiveMatrix;
+	mat4 lightmapMatrix;
+	mat4 specularMatrix;
+	mat4 bumpMatrix; 
+	mat4 refractionMatrix;
+	vec4 vRefractionInfos;
+	vec4 vSpecularColor;
+	vec3 vEmissiveColor;
+	vec4 vDiffuseColor;
+	float pointSize; 
+};
+
+uniform Scene {
+	mat4 viewProjection;
+	mat4 view;
+};

+ 42 - 0
src/Shaders/ShadersInclude/defaultVertexDeclaration.fx

@@ -0,0 +1,42 @@
+// Uniforms
+uniform mat4 viewProjection;
+uniform mat4 view;
+
+#ifdef DIFFUSE
+uniform mat4 diffuseMatrix;
+uniform vec2 vDiffuseInfos;
+#endif
+
+#ifdef AMBIENT
+uniform mat4 ambientMatrix;
+uniform vec2 vAmbientInfos;
+#endif
+
+#ifdef OPACITY
+uniform mat4 opacityMatrix;
+uniform vec2 vOpacityInfos;
+#endif
+
+#ifdef EMISSIVE
+uniform vec2 vEmissiveInfos;
+uniform mat4 emissiveMatrix;
+#endif
+
+#ifdef LIGHTMAP
+uniform vec2 vLightmapInfos;
+uniform mat4 lightmapMatrix;
+#endif
+
+#if defined(SPECULAR) && defined(SPECULARTERM)
+uniform vec2 vSpecularInfos;
+uniform mat4 specularMatrix;
+#endif
+
+#ifdef BUMP
+uniform vec3 vBumpInfos;
+uniform mat4 bumpMatrix;
+#endif
+
+#ifdef POINTSIZE
+	uniform float pointSize;
+#endif

+ 9 - 12
src/Shaders/ShadersInclude/lightFragment.fx

@@ -2,38 +2,35 @@
     #if defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X}) && defined(LIGHTMAPNOSPECULAR{X})
         //No light calculation
     #else
-        #ifndef SPECULARTERM
-            vec3 vLightSpecular{X} = vec3(0.);
-        #endif
         #ifdef SPOTLIGHT{X}
-            info = computeSpotLighting(viewDirectionW, normalW, vLightData{X}, vLightDirection{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightDiffuse{X}.a, glossiness);
+            info = computeSpotLighting(viewDirectionW, normalW, light{X}.vLightData, light{X}.vLightDirection, light{X}.vLightDiffuse.rgb, light{X}.vLightSpecular, light{X}.vLightDiffuse.a, glossiness);
         #endif
         #ifdef HEMILIGHT{X}
-            info = computeHemisphericLighting(viewDirectionW, normalW, vLightData{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightGround{X}, glossiness);
+            info = computeHemisphericLighting(viewDirectionW, normalW, light{X}.vLightData, light{X}.vLightDiffuse.rgb, light{X}.vLightSpecular, light{X}.vLightGround, glossiness);
         #endif
         #if defined(POINTLIGHT{X}) || defined(DIRLIGHT{X})
-            info = computeLighting(viewDirectionW, normalW, vLightData{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightDiffuse{X}.a, glossiness);
+            info = computeLighting(viewDirectionW, normalW, light{X}.vLightData, light{X}.vLightDiffuse.rgb, light{X}.vLightSpecular, light{X}.vLightDiffuse.a, glossiness);
         #endif
     #endif
 	#ifdef SHADOW{X}
 		#ifdef SHADOWESM{X}
 			#if defined(POINTLIGHT{X})
-				shadow = computeShadowWithESMCube(vLightData{X}.xyz, shadowSampler{X}, shadowsInfo{X}.x, shadowsInfo{X}.z);
+				shadow = computeShadowWithESMCube(light{X}.vLightData.xyz, shadowSampler{X}, light{X}.shadowsInfo.x, light{X}.shadowsInfo.z);
 			#else
-				shadow = computeShadowWithESM(vPositionFromLight{X}, shadowSampler{X}, shadowsInfo{X}.x, shadowsInfo{X}.z);
+				shadow = computeShadowWithESM(vPositionFromLight{X}, shadowSampler{X}, light{X}.shadowsInfo.x, light{X}.shadowsInfo.z);
 			#endif
 		#else	
 			#ifdef SHADOWPCF{X}
 				#if defined(POINTLIGHT{X})
-					shadow = computeShadowWithPCFCube(vLightData{X}.xyz, shadowSampler{X}, shadowsInfo{X}.y, shadowsInfo{X}.x);
+					shadow = computeShadowWithPCFCube(light{X}.vLightData.xyz, shadowSampler{X}, light{X}.shadowsInfo.y, light{X}.shadowsInfo.x);
 				#else
-					shadow = computeShadowWithPCF(vPositionFromLight{X}, shadowSampler{X}, shadowsInfo{X}.y, shadowsInfo{X}.x);
+					shadow = computeShadowWithPCF(vPositionFromLight{X}, shadowSampler{X}, light{X}.shadowsInfo.y, light{X}.shadowsInfo.x);
 				#endif
 			#else
 				#if defined(POINTLIGHT{X})
-					shadow = computeShadowCube(vLightData{X}.xyz, shadowSampler{X}, shadowsInfo{X}.x);
+					shadow = computeShadowCube(light{X}.vLightData.xyz, shadowSampler{X}, light{X}.shadowsInfo.x);
 				#else
-					shadow = computeShadow(vPositionFromLight{X}, shadowSampler{X}, shadowsInfo{X}.x);
+					shadow = computeShadow(vPositionFromLight{X}, shadowSampler{X}, light{X}.shadowsInfo.x);
 				#endif
 			#endif
 		#endif

+ 2 - 0
src/Shaders/ShadersInclude/lightFragmentDeclaration.fx

@@ -3,6 +3,8 @@
 	uniform vec4 vLightDiffuse{X};
 	#ifdef SPECULARTERM
 		uniform vec3 vLightSpecular{X};
+	#else
+		vec3 vLightSpecular{X} = vec3(0.);
 	#endif
 	#ifdef SHADOW{X}
 		#if defined(SPOTLIGHT{X}) || defined(DIRLIGHT{X})

+ 25 - 0
src/Shaders/ShadersInclude/lightUboDeclaration.fx

@@ -0,0 +1,25 @@
+#ifdef LIGHT{X}
+	uniform Light{X}
+	{
+		vec4 vLightData;
+		vec4 vLightDiffuse;
+		vec3 vLightSpecular;
+		#ifdef SPOTLIGHT{X}
+			vec4 vLightDirection;
+		#endif
+		#ifdef HEMILIGHT{X}
+			vec3 vLightGround;
+		#endif
+		vec3 shadowsInfo;
+	} light{X};
+
+#ifdef SHADOW{X}
+	#if defined(SPOTLIGHT{X}) || defined(DIRLIGHT{X})
+		varying vec4 vPositionFromLight{X};
+		uniform sampler2D shadowSampler{X};
+	#else
+		uniform samplerCube shadowSampler{X};
+	#endif
+#endif
+
+#endif

+ 92 - 0
src/Shaders/ShadersInclude/pbrFragmentDeclaration.fx

@@ -0,0 +1,92 @@
+uniform vec3 vReflectionColor;
+uniform vec4 vAlbedoColor;
+
+// CUSTOM CONTROLS
+uniform vec4 vLightingIntensity;
+
+#ifdef OVERLOADEDVALUES
+uniform vec4 vOverloadedIntensity;
+uniform vec3 vOverloadedAmbient;
+uniform vec3 vOverloadedAlbedo;
+uniform vec3 vOverloadedReflectivity;
+uniform vec3 vOverloadedEmissive;
+uniform vec3 vOverloadedReflection;
+uniform vec3 vOverloadedMicroSurface;
+#endif
+
+#ifdef OVERLOADEDSHADOWVALUES
+uniform vec4 vOverloadedShadowIntensity;
+#endif
+
+#if defined(REFLECTION) || defined(REFRACTION)
+uniform vec2 vMicrosurfaceTextureLods;
+#endif
+
+uniform vec4 vReflectivityColor;
+uniform vec3 vEmissiveColor;
+
+// Samplers
+#ifdef ALBEDO
+uniform vec2 vAlbedoInfos;
+#endif
+
+#ifdef AMBIENT
+uniform vec3 vAmbientInfos;
+#endif
+
+#ifdef OPACITY	
+uniform vec2 vOpacityInfos;
+#endif
+
+#ifdef EMISSIVE
+uniform vec2 vEmissiveInfos;
+#endif
+
+#ifdef LIGHTMAP
+uniform vec2 vLightmapInfos;
+#endif
+
+#if defined(REFLECTIVITY) || defined(METALLICWORKFLOW) 
+uniform vec3 vReflectivityInfos;
+#endif
+
+#ifdef MICROSURFACEMAP
+uniform vec2 vMicroSurfaceSamplerInfos;
+#endif
+
+#ifdef OPACITYFRESNEL
+uniform vec4 opacityParts;
+#endif
+
+#ifdef EMISSIVEFRESNEL
+uniform vec4 emissiveLeftColor;
+uniform vec4 emissiveRightColor;
+#endif
+
+// Refraction Reflection
+#if defined(REFLECTIONMAP_SPHERICAL) || defined(REFLECTIONMAP_PROJECTION) || defined(REFRACTION)
+uniform mat4 view;
+#endif
+
+// Refraction
+#ifdef REFRACTION
+uniform vec4 vRefractionInfos;
+
+#ifdef REFRACTIONMAP_3D
+#else
+uniform mat4 refractionMatrix;
+#endif
+#endif
+
+// Reflection
+#ifdef REFLECTION
+uniform vec2 vReflectionInfos;
+
+#ifdef REFLECTIONMAP_SKYBOX
+#else
+
+#if defined(REFLECTIONMAP_PLANAR) || defined(REFLECTIONMAP_CUBIC) || defined(REFLECTIONMAP_PROJECTION)
+uniform mat4 reflectionMatrix;
+#endif
+#endif
+#endif

+ 9 - 12
src/Shaders/ShadersInclude/pbrLightFunctionsCall.fx

@@ -2,39 +2,36 @@
     #if defined(LIGHTMAP) && defined(LIGHTMAPEXCLUDED{X}) && defined(LIGHTMAPNOSPECULAR{X})
         //No light calculation
     #else
-        #ifndef SPECULARTERM
-            vec3 vLightSpecular{X} = vec3(0.0);
-        #endif
         #ifdef SPOTLIGHT{X}
-            info = computeSpotLighting(viewDirectionW, normalW, vLightData{X}, vLightDirection{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightDiffuse{X}.a, roughness, NdotV, specularEnvironmentR90, NdotL);
+            info = computeSpotLighting(viewDirectionW, normalW, light{X}.vLightData, light{X}.vLightDirection, light{X}.vLightDiffuse.rgb, light{X}.vLightSpecular, light{X}.vLightDiffuse.a, roughness, NdotV, specularEnvironmentR90, NdotL);
         #endif
         #ifdef HEMILIGHT{X}
-            info = computeHemisphericLighting(viewDirectionW, normalW, vLightData{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightGround{X}, roughness, NdotV, specularEnvironmentR90, NdotL);
+            info = computeHemisphericLighting(viewDirectionW, normalW, light{X}.vLightData, light{X}.vLightDiffuse.rgb, light{X}.vLightSpecular, light{X}.vLightGround, roughness, NdotV, specularEnvironmentR90, NdotL);
         #endif
         #if defined(POINTLIGHT{X}) || defined(DIRLIGHT{X})
-            info = computeLighting(viewDirectionW, normalW, vLightData{X}, vLightDiffuse{X}.rgb, vLightSpecular{X}, vLightDiffuse{X}.a, roughness, NdotV, specularEnvironmentR90, NdotL);
+            info = computeLighting(viewDirectionW, normalW, light{X}.vLightData, light{X}.vLightDiffuse.rgb, light{X}.vLightSpecular, light{X}.vLightDiffuse.a, roughness, NdotV, specularEnvironmentR90, NdotL);
         #endif
     #endif
     
     #ifdef SHADOW{X}
         #ifdef SHADOWESM{X}
 			#if defined(POINTLIGHT{X})
-				notShadowLevel = computeShadowWithESMCube(vLightData{X}.xyz, shadowSampler{X}, shadowsInfo{X}.x, shadowsInfo{X}.z);
+				notShadowLevel = computeShadowWithESMCube(light{X}.vLightData.xyz, shadowSampler{X}, light{X}.shadowsInfo.x, light{X}.shadowsInfo.z);
 			#else
-				notShadowLevel = computeShadowWithESM(vPositionFromLight{X}, shadowSampler{X}, shadowsInfo{X}.x, shadowsInfo{X}.z);
+				notShadowLevel = computeShadowWithESM(light{X}.vPositionFromLight, shadowSampler{X}, light{X}.shadowsInfo.x, light{X}.shadowsInfo.z);
 			#endif
         #else
             #ifdef SHADOWPCF{X}
                 #if defined(POINTLIGHT{X})
-                    notShadowLevel = computeShadowWithPCFCube(vLightData{X}.xyz, shadowSampler{X}, shadowsInfo{X}.y, shadowsInfo{X}.x);
+                    notShadowLevel = computeShadowWithPCFCube(light{X}.vLightData.xyz, shadowSampler{X}, light{X}.shadowsInfo.y, light{X}.shadowsInfo.x);
                 #else
-                    notShadowLevel = computeShadowWithPCF(vPositionFromLight{X}, shadowSampler{X}, shadowsInfo{X}.y, shadowsInfo{X}.x);
+                    notShadowLevel = computeShadowWithPCF(vPositionFromLight{X}, shadowSampler{X}, light{X}.shadowsInfo.y, light{X}.shadowsInfo.x);
                 #endif
             #else
                 #if defined(POINTLIGHT{X})
-                    notShadowLevel = computeShadowCube(vLightData{X}.xyz, shadowSampler{X}, shadowsInfo{X}.x);
+                    notShadowLevel = computeShadowCube(light{X}.vLightData.xyz, shadowSampler{X}, light{X}.shadowsInfo.x);
                 #else
-                    notShadowLevel = computeShadow(vPositionFromLight{X}, shadowSampler{X}, shadowsInfo{X}.x);
+                    notShadowLevel = computeShadow(vPositionFromLight{X}, shadowSampler{X}, light{X}.shadowsInfo.x);
                 #endif
             #endif
         #endif

+ 52 - 0
src/Shaders/ShadersInclude/pbrUboDeclaration.fx

@@ -0,0 +1,52 @@
+layout(std140, column_major) uniform;
+
+uniform Material
+{
+	uniform vec2 vAlbedoInfos;
+	uniform vec3 vAmbientInfos;
+	uniform vec2 vOpacityInfos;
+	uniform vec2 vEmissiveInfos;
+	uniform vec2 vLightmapInfos;
+	uniform vec3 vReflectivityInfos;
+	uniform vec2 vMicroSurfaceSamplerInfos;
+	uniform vec4 vRefractionInfos;
+	uniform vec2 vReflectionInfos;
+	uniform vec3 vBumpInfos;
+	uniform mat4 albedoMatrix;
+	uniform mat4 ambientMatrix;
+	uniform mat4 opacityMatrix;
+	uniform mat4 emissiveMatrix;
+	uniform mat4 lightmapMatrix;
+	uniform mat4 reflectivityMatrix;
+	uniform mat4 microSurfaceSamplerMatrix;
+	uniform mat4 bumpMatrix;
+	uniform mat4 refractionMatrix;
+	uniform mat4 reflectionMatrix;
+
+	uniform vec3 vReflectionColor;
+	uniform vec4 vAlbedoColor;
+	uniform vec4 vLightingIntensity;
+
+	uniform vec2 vMicrosurfaceTextureLods;
+	uniform vec4 vReflectivityColor;
+	uniform vec3 vEmissiveColor;
+	uniform vec4 opacityParts;
+	uniform vec4 emissiveLeftColor;
+	uniform vec4 emissiveRightColor;
+
+	uniform vec4 vOverloadedIntensity;
+	uniform vec3 vOverloadedAmbient;
+	uniform vec3 vOverloadedAlbedo;
+	uniform vec3 vOverloadedReflectivity;
+	uniform vec3 vOverloadedEmissive;
+	uniform vec3 vOverloadedReflection;
+	uniform vec3 vOverloadedMicroSurface;
+	uniform vec4 vOverloadedShadowIntensity;
+
+	uniform float pointSize;
+};
+
+uniform Scene {
+	mat4 viewProjection;
+	mat4 view;
+};

+ 46 - 0
src/Shaders/ShadersInclude/pbrVertexDeclaration.fx

@@ -0,0 +1,46 @@
+uniform mat4 view;
+uniform mat4 viewProjection;
+
+#ifdef ALBEDO
+uniform mat4 albedoMatrix;
+uniform vec2 vAlbedoInfos;
+#endif
+
+#ifdef AMBIENT
+uniform mat4 ambientMatrix;
+uniform vec3 vAmbientInfos;
+#endif
+
+#ifdef OPACITY
+uniform mat4 opacityMatrix;
+uniform vec2 vOpacityInfos;
+#endif
+
+#ifdef EMISSIVE
+uniform vec2 vEmissiveInfos;
+uniform mat4 emissiveMatrix;
+#endif
+
+#ifdef LIGHTMAP
+uniform vec2 vLightmapInfos;
+uniform mat4 lightmapMatrix;
+#endif
+
+#if defined(REFLECTIVITY) || defined(METALLICWORKFLOW) 
+uniform vec3 vReflectivityInfos;
+uniform mat4 reflectivityMatrix;
+#endif
+
+#ifdef MICROSURFACEMAP
+uniform vec2 vMicroSurfaceSamplerInfos;
+uniform mat4 microSurfaceSamplerMatrix;
+#endif
+
+#ifdef BUMP
+uniform vec3 vBumpInfos;
+uniform mat4 bumpMatrix;
+#endif
+
+#ifdef POINTSIZE
+uniform float pointSize;
+#endif

+ 1 - 1
src/Shaders/ShadersInclude/pointCloudVertexDeclaration.fx

@@ -1,3 +1,3 @@
-#ifdef POINTSIZE
+#ifdef POINTSIZE
 	uniform float pointSize;
 #endif

+ 4 - 48
src/Shaders/default.fragment.fx

@@ -1,4 +1,6 @@
-#ifdef BUMP
+#include<__decl__defaultFragment>
+
+#ifdef BUMP
 #extension GL_OES_standard_derivatives : enable
 #endif
 
@@ -11,11 +13,6 @@
 
 uniform vec3 vEyePosition;
 uniform vec3 vAmbientColor;
-uniform vec4 vDiffuseColor;
-#ifdef SPECULARTERM
-uniform vec4 vSpecularColor;
-#endif
-uniform vec3 vEmissiveColor;
 
 // Input
 varying vec3 vPositionW;
@@ -32,7 +29,7 @@ varying vec4 vColor;
 #include<helperFunctions>
 
 // Lights
-#include<lightFragmentDeclaration>[0..maxSimultaneousLights]
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
 
 #include<lightsFragmentFunctions>
 #include<shadowsFragmentFunctions>
@@ -41,80 +38,48 @@ varying vec4 vColor;
 #ifdef DIFFUSE
 varying vec2 vDiffuseUV;
 uniform sampler2D diffuseSampler;
-uniform vec2 vDiffuseInfos;
 #endif
 
 #ifdef AMBIENT
 varying vec2 vAmbientUV;
 uniform sampler2D ambientSampler;
-uniform vec2 vAmbientInfos;
 #endif
 
 #ifdef OPACITY	
 varying vec2 vOpacityUV;
 uniform sampler2D opacitySampler;
-uniform vec2 vOpacityInfos;
 #endif
 
 #ifdef EMISSIVE
 varying vec2 vEmissiveUV;
-uniform vec2 vEmissiveInfos;
 uniform sampler2D emissiveSampler;
 #endif
 
 #ifdef LIGHTMAP
 varying vec2 vLightmapUV;
-uniform vec2 vLightmapInfos;
 uniform sampler2D lightmapSampler;
 #endif
 
-#if defined(REFLECTIONMAP_SPHERICAL) || defined(REFLECTIONMAP_PROJECTION) || defined(REFRACTION)
-uniform mat4 view;
-#endif
-
 #ifdef REFRACTION
-uniform vec4 vRefractionInfos;
 
 #ifdef REFRACTIONMAP_3D
 uniform samplerCube refractionCubeSampler;
 #else
 uniform sampler2D refraction2DSampler;
-uniform mat4 refractionMatrix;
 #endif
 
-#ifdef REFRACTIONFRESNEL
-uniform vec4 refractionLeftColor;
-uniform vec4 refractionRightColor;
-#endif
 #endif
 
 #if defined(SPECULAR) && defined(SPECULARTERM)
 varying vec2 vSpecularUV;
-uniform vec2 vSpecularInfos;
 uniform sampler2D specularSampler;
 #endif
 
 // Fresnel
 #include<fresnelFunction>
 
-#ifdef DIFFUSEFRESNEL
-uniform vec4 diffuseLeftColor;
-uniform vec4 diffuseRightColor;
-#endif
-
-#ifdef OPACITYFRESNEL
-uniform vec4 opacityParts;
-#endif
-
-#ifdef EMISSIVEFRESNEL
-uniform vec4 emissiveLeftColor;
-uniform vec4 emissiveRightColor;
-#endif
-
 // Reflection
 #ifdef REFLECTION
-uniform vec2 vReflectionInfos;
-
 #ifdef REFLECTIONMAP_3D
 uniform samplerCube reflectionCubeSampler;
 #else
@@ -128,18 +93,10 @@ varying vec3 vPositionUVW;
 varying vec3 vDirectionW;
 #endif
 
-#if defined(REFLECTIONMAP_PLANAR) || defined(REFLECTIONMAP_CUBIC) || defined(REFLECTIONMAP_PROJECTION)
-uniform mat4 reflectionMatrix;
-#endif
 #endif
 
 #include<reflectionFunction>
 
-#ifdef REFLECTIONFRESNEL
-uniform vec4 reflectionLeftColor;
-uniform vec4 reflectionRightColor;
-#endif
-
 #endif
 
 #ifdef CAMERACOLORGRADING
@@ -411,6 +368,5 @@ void main(void) {
 #ifdef CAMERACOLORCURVES
 	color.rgb = applyColorCurves(color.rgb);
 #endif
-
 	gl_FragColor = color;
 }

+ 3 - 20
src/Shaders/default.vertex.fx

@@ -1,4 +1,6 @@
-// Attributes
+#include<__decl__defaultVertex>
+
+// Attributes
 attribute vec3 position;
 #ifdef NORMAL
 attribute vec3 normal;
@@ -21,53 +23,34 @@ attribute vec4 color;
 // Uniforms
 #include<instancesDeclaration>
 
-uniform mat4 view;
-uniform mat4 viewProjection;
-
 #ifdef DIFFUSE
 varying vec2 vDiffuseUV;
-uniform mat4 diffuseMatrix;
-uniform vec2 vDiffuseInfos;
 #endif
 
 #ifdef AMBIENT
 varying vec2 vAmbientUV;
-uniform mat4 ambientMatrix;
-uniform vec2 vAmbientInfos;
 #endif
 
 #ifdef OPACITY
 varying vec2 vOpacityUV;
-uniform mat4 opacityMatrix;
-uniform vec2 vOpacityInfos;
 #endif
 
 #ifdef EMISSIVE
 varying vec2 vEmissiveUV;
-uniform vec2 vEmissiveInfos;
-uniform mat4 emissiveMatrix;
 #endif
 
 #ifdef LIGHTMAP
 varying vec2 vLightmapUV;
-uniform vec2 vLightmapInfos;
-uniform mat4 lightmapMatrix;
 #endif
 
 #if defined(SPECULAR) && defined(SPECULARTERM)
 varying vec2 vSpecularUV;
-uniform vec2 vSpecularInfos;
-uniform mat4 specularMatrix;
 #endif
 
 #ifdef BUMP
 varying vec2 vBumpUV;
-uniform vec3 vBumpInfos;
-uniform mat4 bumpMatrix;
 #endif
 
-#include<pointCloudVertexDeclaration>
-
 // Output
 varying vec3 vPositionW;
 #ifdef NORMAL

+ 4 - 54
src/Shaders/pbr.fragment.fx

@@ -12,36 +12,12 @@
 
 precision highp float;
 
+#include<__decl__pbrFragment>
+
 uniform vec3 vEyePosition;
 uniform vec3 vAmbientColor;
-uniform vec3 vReflectionColor;
-uniform vec4 vAlbedoColor;
-
-// CUSTOM CONTROLS
-uniform vec4 vLightingIntensity;
 uniform vec4 vCameraInfos;
 
-#ifdef OVERLOADEDVALUES
-uniform vec4 vOverloadedIntensity;
-uniform vec3 vOverloadedAmbient;
-uniform vec3 vOverloadedAlbedo;
-uniform vec3 vOverloadedReflectivity;
-uniform vec3 vOverloadedEmissive;
-uniform vec3 vOverloadedReflection;
-uniform vec3 vOverloadedMicroSurface;
-#endif
-
-#ifdef OVERLOADEDSHADOWVALUES
-uniform vec4 vOverloadedShadowIntensity;
-#endif
-
-#if defined(REFLECTION) || defined(REFRACTION)
-uniform vec2 vMicrosurfaceTextureLods;
-#endif
-
-uniform vec4 vReflectivityColor;
-uniform vec3 vEmissiveColor;
-
 // Input
 varying vec3 vPositionW;
 
@@ -54,83 +30,60 @@ varying vec4 vColor;
 #endif
 
 // Lights
-#include<lightFragmentDeclaration>[0..maxSimultaneousLights]
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
 
 // Samplers
 #ifdef ALBEDO
 varying vec2 vAlbedoUV;
 uniform sampler2D albedoSampler;
-uniform vec2 vAlbedoInfos;
 #endif
 
 #ifdef AMBIENT
 varying vec2 vAmbientUV;
 uniform sampler2D ambientSampler;
-uniform vec3 vAmbientInfos;
 #endif
 
 #ifdef OPACITY	
 varying vec2 vOpacityUV;
 uniform sampler2D opacitySampler;
-uniform vec2 vOpacityInfos;
 #endif
 
 #ifdef EMISSIVE
 varying vec2 vEmissiveUV;
-uniform vec2 vEmissiveInfos;
 uniform sampler2D emissiveSampler;
 #endif
 
 #ifdef LIGHTMAP
 varying vec2 vLightmapUV;
-uniform vec2 vLightmapInfos;
 uniform sampler2D lightmapSampler;
 #endif
 
 #if defined(REFLECTIVITY) || defined(METALLICWORKFLOW) 
 varying vec2 vReflectivityUV;
-uniform vec3 vReflectivityInfos;
 uniform sampler2D reflectivitySampler;
 #endif
 
 #ifdef MICROSURFACEMAP
 varying vec2 vMicroSurfaceSamplerUV;
-uniform vec2 vMicroSurfaceSamplerInfos;
 uniform sampler2D microSurfaceSampler;
 #endif
 
 // Fresnel
 #include<fresnelFunction>
 
-#ifdef OPACITYFRESNEL
-uniform vec4 opacityParts;
-#endif
-
-#ifdef EMISSIVEFRESNEL
-uniform vec4 emissiveLeftColor;
-uniform vec4 emissiveRightColor;
-#endif
-
-// Refraction Reflection
-#if defined(REFLECTIONMAP_SPHERICAL) || defined(REFLECTIONMAP_PROJECTION) || defined(REFRACTION)
-uniform mat4 view;
-#endif
-
 // Refraction
 #ifdef REFRACTION
-uniform vec4 vRefractionInfos;
+
 
 #ifdef REFRACTIONMAP_3D
 uniform samplerCube refractionCubeSampler;
 #else
 uniform sampler2D refraction2DSampler;
-uniform mat4 refractionMatrix;
 #endif
 #endif
 
 // Reflection
 #ifdef REFLECTION
-uniform vec2 vReflectionInfos;
 
 #ifdef REFLECTIONMAP_3D
 uniform samplerCube reflectionCubeSampler;
@@ -145,9 +98,6 @@ varying vec3 vPositionUVW;
 varying vec3 vDirectionW;
 #endif
 
-#if defined(REFLECTIONMAP_PLANAR) || defined(REFLECTIONMAP_CUBIC) || defined(REFLECTIONMAP_PROJECTION)
-uniform mat4 reflectionMatrix;
-#endif
 #endif
 
 #include<reflectionFunction>

+ 2 - 24
src/Shaders/pbr.vertex.fx

@@ -1,5 +1,7 @@
 precision highp float;
 
+#include<__decl__pbrVertex>
+
 // Attributes
 attribute vec3 position;
 #ifdef NORMAL
@@ -23,59 +25,36 @@ attribute vec4 color;
 // Uniforms
 #include<instancesDeclaration>
 
-uniform mat4 view;
-uniform mat4 viewProjection;
-
 #ifdef ALBEDO
 varying vec2 vAlbedoUV;
-uniform mat4 albedoMatrix;
-uniform vec2 vAlbedoInfos;
 #endif
 
 #ifdef AMBIENT
 varying vec2 vAmbientUV;
-uniform mat4 ambientMatrix;
-uniform vec3 vAmbientInfos;
 #endif
 
 #ifdef OPACITY
 varying vec2 vOpacityUV;
-uniform mat4 opacityMatrix;
-uniform vec2 vOpacityInfos;
 #endif
 
 #ifdef EMISSIVE
 varying vec2 vEmissiveUV;
-uniform vec2 vEmissiveInfos;
-uniform mat4 emissiveMatrix;
 #endif
 
 #ifdef LIGHTMAP
 varying vec2 vLightmapUV;
-uniform vec2 vLightmapInfos;
-uniform mat4 lightmapMatrix;
 #endif
 
 #if defined(REFLECTIVITY) || defined(METALLICWORKFLOW) 
 varying vec2 vReflectivityUV;
-uniform vec3 vReflectivityInfos;
-uniform mat4 reflectivityMatrix;
 #endif
 
 #ifdef MICROSURFACEMAP
 varying vec2 vMicroSurfaceSamplerUV;
-uniform vec2 vMicroSurfaceSamplerInfos;
-uniform mat4 microSurfaceSamplerMatrix;
 #endif
 
 #ifdef BUMP
 varying vec2 vBumpUV;
-uniform vec3 vBumpInfos;
-uniform mat4 bumpMatrix;
-#endif
-
-#ifdef POINTSIZE
-uniform float pointSize;
 #endif
 
 // Output
@@ -88,7 +67,6 @@ varying vec3 vNormalW;
 varying vec4 vColor;
 #endif
 
-
 #include<bumpVertexDeclaration>
 #include<clipPlaneVertexDeclaration>
 #include<fogVertexDeclaration>

+ 73 - 1
src/babylon.engine.ts

@@ -577,7 +577,7 @@
             // GL
             if (!options.disableWebGL2Support) {
                 try {
-                    this._gl = <WebGLRenderingContext>(canvas.getContext("webgl2", options) || canvas.getContext("experimental-webgl2", options));
+                    this._gl = <WebGL2RenderingContext>(canvas.getContext("webgl2", options) || canvas.getContext("experimental-webgl2", options));
                     if (this._gl) {
                         this._webGLVersion = 2.0;
                     }
@@ -1305,6 +1305,64 @@
             this.wipeCaches();
         }
 
+        // UBOs
+        public createUniformBuffer(elements: number[] | Float32Array): WebGLBuffer {
+            var ubo = this._gl.createBuffer();
+            this.bindUniformBuffer(ubo);
+
+            if (elements instanceof Float32Array) {
+                this._gl.bufferData(this._gl.UNIFORM_BUFFER, <Float32Array>elements, this._gl.STATIC_DRAW);
+            } else {
+                this._gl.bufferData(this._gl.UNIFORM_BUFFER, new Float32Array(<number[]>elements), this._gl.STATIC_DRAW);
+            }
+
+            this.bindUniformBuffer(null);
+
+            ubo.references = 1;
+            return ubo;
+        }
+
+        public createDynamicUniformBuffer(elements: number[] | Float32Array): WebGLBuffer {
+            var ubo = this._gl.createBuffer();
+            this.bindUniformBuffer(ubo);
+
+            if (elements instanceof Float32Array) {
+                this._gl.bufferData(this._gl.UNIFORM_BUFFER, <Float32Array>elements, this._gl.DYNAMIC_DRAW);
+            } else {
+                this._gl.bufferData(this._gl.UNIFORM_BUFFER, new Float32Array(<number[]>elements), this._gl.DYNAMIC_DRAW);
+            }
+
+            this.bindUniformBuffer(null);
+
+            ubo.references = 1;
+            return ubo;
+        }
+
+        public updateUniformBuffer(uniformBuffer: WebGLBuffer, elements: number[] | Float32Array, offset?: number, count?: number): void {
+            this.bindUniformBuffer(uniformBuffer);
+
+            if (offset === undefined) {
+                offset = 0;
+            }
+
+            if (count === undefined) {
+                if (elements instanceof Float32Array) {
+                    this._gl.bufferSubData(this._gl.UNIFORM_BUFFER, offset, <Float32Array>elements);
+                } else {
+                    this._gl.bufferSubData(this._gl.UNIFORM_BUFFER, offset, new Float32Array(<number[]>elements));
+                }
+            } else {
+                if (elements instanceof Float32Array) {
+                    this._gl.bufferSubData(this._gl.UNIFORM_BUFFER, 0, <Float32Array>elements.subarray(offset, offset + count));
+                } else {
+                    this._gl.bufferSubData(this._gl.UNIFORM_BUFFER, 0, new Float32Array(<number[]>elements).subarray(offset, offset + count));
+                }
+            }
+
+            this.bindUniformBuffer(null);
+        }
+
+
         // VBOs
         private _resetVertexBufferBinding(): void {
             this.bindArrayBuffer(null);
@@ -1416,6 +1474,20 @@
             this.bindBuffer(buffer, this._gl.ARRAY_BUFFER);
         }
 
+        public bindUniformBuffer(buffer?: WebGLBuffer): void {
+            this._gl.bindBuffer(this._gl.UNIFORM_BUFFER, buffer);
+        }
+
+        public bindUniformBufferBase(buffer: WebGLBuffer, location: number): void {
+            this._gl.bindBufferBase(this._gl.UNIFORM_BUFFER, location, buffer);
+        }
+
+        public bindUniformBlock(shaderProgram: WebGLProgram, blockName: string, index: number): void {
+            var uniformLocation = this._gl.getUniformBlockIndex(shaderProgram, blockName);
+
+            this._gl.uniformBlockBinding(shaderProgram, uniformLocation, index);
+        };
+
         private bindIndexBuffer(buffer: WebGLBuffer): void {
             if (!this._vaoRecordInProgress) {
                 this._unBindVertexArrayObject();

+ 6 - 4
src/babylon.mixins.ts

@@ -28,10 +28,6 @@ interface Window {
     VRFrameData: any; // WebVR, from specs 1.1
 }
 
-interface WebGLVertexArrayObject {
-
-}
-
 interface WebGLRenderingContext {
     drawArraysInstanced(mode: number, first: number, count: number, primcount: number): void;
     drawElementsInstanced(mode: number, count: number, type: number, offset: number, primcount: number): void;
@@ -44,10 +40,16 @@ interface WebGLRenderingContext {
     blitFramebuffer(srcX0: number, srcY0: number, srcX1: number, srcY1: number, dstX0: number, dstY0: number, dstX1: number, dstY1: number, mask: number, filter: number): void;
     renderbufferStorageMultisample(target: number, samples: number, internalformat: number, width: number, height: number): void;
 
+    bindBufferBase(target: number, index: number, buffer: WebGLBuffer | null): void;
+    getUniformBlockIndex(program: WebGLProgram, uniformBlockName: string): number;
+    uniformBlockBinding(program: WebGLProgram, uniformBlockIndex: number, uniformBlockBinding: number): void;
+
     MAX_SAMPLES: number;
     RGBA8: number;
     READ_FRAMEBUFFER: number;
     DRAW_FRAMEBUFFER: number;
+    UNIFORM_BUFFER: number;
+
 }
 
 interface HTMLURL {

+ 24 - 0
src/babylon.scene.ts

@@ -682,6 +682,8 @@
         public _activeAnimatables = new Array<Animatable>();
 
         private _transformMatrix = Matrix.Zero();
+        private _sceneUbo: UniformBuffer;
+
         private _pickWithRayInverseMatrix: Matrix;
 
         private _edgesRenderers = new SmartArray<EdgesRenderer>(16);
@@ -744,6 +746,9 @@
 
             //collision coordinator initialization. For now legacy per default.
             this.workerCollisions = false;//(!!Worker && (!!BABYLON.CollisionWorker || BABYLON.WorkerIncluded));
+
+            // Uniform Buffer
+            this._createUbo();
         }
 
         // Properties
@@ -935,6 +940,12 @@
             }
         }
 
+        private _createUbo(): void {
+            this._sceneUbo = new UniformBuffer(this._engine, null, true);
+            this._sceneUbo.addUniform("viewProjection", 16);
+            this._sceneUbo.addUniform("view", 16);
+        }
+
         // Pointers handling
 
         /**
@@ -1691,6 +1702,16 @@
             } else {
                 Frustum.GetPlanesToRef(this._transformMatrix, this._frustumPlanes);
             }
+
+            if (this._sceneUbo.useUbo) {
+                this._sceneUbo.updateMatrix("viewProjection", this._transformMatrix);
+                this._sceneUbo.updateMatrix("view", this._viewMatrix);
+                this._sceneUbo.update();
+            }
+        }
+
+        public getSceneUniformBuffer(): UniformBuffer {
+            return this._sceneUbo;
         }
 
         // Methods
@@ -3194,6 +3215,9 @@
                 this.textures[0].dispose();
             }
 
+            // Release UBO
+            this._sceneUbo.dispose();
+
             // Post-processes
             this.postProcessManager.dispose();
 

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1176 - 0
src/babylon.webgl2.ts