Browse Source

Merge remote-tracking branch 'upstream/master' into bug-fixes

Gary Hsu 8 years ago
parent
commit
9bc0012afd
99 changed files with 48542 additions and 27644 deletions
  1. 0 158
      Playground/js/perf.js
  2. 0 77
      Playground/perf.html
  3. 19 11
      Tools/Gulp/config.json
  4. 2832 2815
      dist/preview release/babylon.d.ts
  5. 45 45
      dist/preview release/babylon.js
  6. 265 84
      dist/preview release/babylon.max.js
  7. 2832 2815
      dist/preview release/babylon.module.d.ts
  8. 45 45
      dist/preview release/babylon.worker.js
  9. 2137 2116
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts
  10. 51 37
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js
  11. 37237 17140
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js
  12. 2137 2116
      dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts
  13. 45 0
      dist/preview release/gui/babylon.gui.d.ts
  14. 178 10
      dist/preview release/gui/babylon.gui.js
  15. 3 3
      dist/preview release/gui/babylon.gui.min.js
  16. 45 0
      dist/preview release/gui/babylon.gui.module.d.ts
  17. 2 1
      dist/preview release/materialsLibrary/babylon.cellMaterial.js
  18. 1 1
      dist/preview release/materialsLibrary/babylon.cellMaterial.min.js
  19. 2 1
      dist/preview release/materialsLibrary/babylon.fireMaterial.js
  20. 1 1
      dist/preview release/materialsLibrary/babylon.fireMaterial.min.js
  21. 2 1
      dist/preview release/materialsLibrary/babylon.furMaterial.js
  22. 1 1
      dist/preview release/materialsLibrary/babylon.furMaterial.min.js
  23. 2 1
      dist/preview release/materialsLibrary/babylon.gradientMaterial.js
  24. 1 1
      dist/preview release/materialsLibrary/babylon.gradientMaterial.min.js
  25. 2 1
      dist/preview release/materialsLibrary/babylon.lavaMaterial.js
  26. 1 1
      dist/preview release/materialsLibrary/babylon.lavaMaterial.min.js
  27. 2 1
      dist/preview release/materialsLibrary/babylon.normalMaterial.js
  28. 1 1
      dist/preview release/materialsLibrary/babylon.normalMaterial.min.js
  29. 2 1
      dist/preview release/materialsLibrary/babylon.simpleMaterial.js
  30. 1 1
      dist/preview release/materialsLibrary/babylon.simpleMaterial.min.js
  31. 2 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.js
  32. 1 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.min.js
  33. 2 1
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.js
  34. 1 1
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.min.js
  35. 1 0
      dist/preview release/materialsLibrary/babylon.waterMaterial.js
  36. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  37. 2 0
      dist/preview release/what's new.md
  38. 6 0
      gui/src/advancedDynamicTexture.ts
  39. 10 0
      gui/src/controls/container.ts
  40. 10 0
      gui/src/controls/control.ts
  41. 41 10
      gui/src/controls/inputText.ts
  42. 136 0
      gui/src/controls/virtualKeyboard.ts
  43. 4 3
      localDev/index.html
  44. 1 0
      materialsLibrary/src/cell/babylon.cellMaterial.ts
  45. 2 0
      materialsLibrary/src/cell/cell.fragment.fx
  46. 1 0
      materialsLibrary/src/fire/babylon.fireMaterial.ts
  47. 2 0
      materialsLibrary/src/fire/fire.fragment.fx
  48. 1 0
      materialsLibrary/src/fur/babylon.furMaterial.ts
  49. 2 0
      materialsLibrary/src/fur/fur.fragment.fx
  50. 1 0
      materialsLibrary/src/gradient/babylon.gradientMaterial.ts
  51. 2 0
      materialsLibrary/src/gradient/gradient.fragment.fx
  52. 1 0
      materialsLibrary/src/lava/babylon.lavaMaterial.ts
  53. 2 0
      materialsLibrary/src/lava/lava.fragment.fx
  54. 1 0
      materialsLibrary/src/normal/babylon.normalMaterial.ts
  55. 2 0
      materialsLibrary/src/normal/normal.fragment.fx
  56. 1 0
      materialsLibrary/src/simple/babylon.simpleMaterial.ts
  57. 2 0
      materialsLibrary/src/simple/simple.fragment.fx
  58. 1 0
      materialsLibrary/src/terrain/babylon.terrainMaterial.ts
  59. 2 0
      materialsLibrary/src/terrain/terrain.fragment.fx
  60. 1 0
      materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts
  61. 2 0
      materialsLibrary/src/triPlanar/triplanar.fragment.fx
  62. 1 0
      materialsLibrary/src/water/babylon.waterMaterial.ts
  63. 7 5
      src/Behaviors/Cameras/babylon.framingBehavior.ts
  64. 39 8
      src/Cameras/Inputs/babylon.arcRotateCameraPointersInput.ts
  65. 22 4
      src/Cameras/babylon.arcRotateCamera.ts
  66. 16 2
      src/Cameras/babylon.camera.ts
  67. 2 2
      src/Cameras/babylon.targetCamera.ts
  68. 11 1
      src/Layer/babylon.highlightlayer.ts
  69. 11 1
      src/Lights/Shadows/babylon.shadowGenerator.ts
  70. 1 0
      src/Materials/PBR/babylon.pbrBaseMaterial.ts
  71. 2 0
      src/Materials/Textures/babylon.mirrorTexture.ts
  72. 16 0
      src/Materials/Textures/babylon.multiRenderTarget.ts
  73. 1 1
      src/Materials/Textures/babylon.renderTargetTexture.ts
  74. 6 2
      src/Materials/babylon.effect.ts
  75. 3 0
      src/Materials/babylon.material.ts
  76. 5 0
      src/Materials/babylon.materialHelper.ts
  77. 1 0
      src/Materials/babylon.standardMaterial.ts
  78. 3 1
      src/PostProcess/RenderPipeline/Pipelines/babylon.defaultRenderingPipeline.ts
  79. 1 1
      src/PostProcess/RenderPipeline/Pipelines/babylon.ssao2RenderingPipeline.ts
  80. 2 3
      src/PostProcess/RenderPipeline/Pipelines/babylon.standardRenderingPipeline.ts
  81. 11 1
      src/PostProcess/babylon.postProcess.ts
  82. 9 1
      src/PostProcess/babylon.volumetricLightScatteringPostProcess.ts
  83. 1 1
      src/PostProcess/babylon.vrDistortionCorrectionPostProcess.ts
  84. 9 1
      src/Rendering/babylon.depthRenderer.ts
  85. 12 2
      src/Rendering/babylon.geometryBufferRenderer.ts
  86. 25 11
      src/Rendering/babylon.outlineRenderer.ts
  87. 39 3
      src/Rendering/babylon.renderingGroup.ts
  88. 1 1
      src/Rendering/babylon.renderingManager.ts
  89. 4 0
      src/Shaders/ShadersInclude/depthPrePass.fx
  90. 3 0
      src/Shaders/ShadersInclude/mrtFragmentDeclaration.fx
  91. 2 0
      src/Shaders/default.fragment.fx
  92. 13 13
      src/Shaders/geometry.fragment.fx
  93. 10 12
      src/Shaders/geometry.vertex.fx
  94. 6 2
      src/Shaders/outline.fragment.fx
  95. 2 0
      src/Shaders/outline.vertex.fx
  96. 2 0
      src/Shaders/pbr.fragment.fx
  97. 2 2
      src/Shaders/ssao2.fragment.fx
  98. 17 15
      src/Tools/babylon.tools.ts
  99. 88 44
      src/babylon.engine.ts

+ 0 - 158
Playground/js/perf.js

@@ -1,158 +0,0 @@
-(function () {
-    var snippetUrl = "https://babylonjs-api2.azurewebsites.net/snippets";
-    var currentSnippetToken;
-    var engine;
-    var scripts;
-    var zipCode;
-    BABYLON.Engine.ShadersRepository = "/src/Shaders/";
-    var loadScript = function (scriptURL, title) {
-        var xhr = new XMLHttpRequest();
-
-        xhr.open('GET', scriptURL, true);
-
-        xhr.onreadystatechange = function () {
-            if (xhr.readyState === 4) {
-                if (xhr.status === 200) {
-                    blockEditorChange = true;
-                    console.log(xhr.responseText);
-                    jsEditor.setValue(xhr.responseText);
-                    jsEditor.setPosition({ lineNumber: 0, column: 0 });
-                    blockEditorChange = false;
-                    compileAndRun();
-
-                    document.getElementById("currentScript").innerHTML = title;
-
-                    currentSnippetToken = null;
-                }
-            }
-        };
-
-        xhr.send(null);
-    };
-
-    var showError = function(error) {
-        console.warn(error);
-    };
-
-    compileAndRun = function (code) {
-        try {
-
-            if (!BABYLON.Engine.isSupported()) {
-                showError("Your browser does not support WebGL");
-                return;
-            }
-
-            if (engine) {
-                engine.dispose();
-                engine = null;
-            }
-
-            var canvas = document.getElementById("renderCanvas");
-            engine = new BABYLON.Engine(canvas, true, {stencil: true});
-            engine.renderEvenInBackground = false;
-            BABYLON.Camera.ForceAttachControlToAlwaysPreventDefault = true;
-
-            engine.runRenderLoop(function () {
-                if (engine.scenes.length === 0) {
-                    return;
-                }
-
-                if (canvas.width !== canvas.clientWidth) {
-                    engine.resize();
-                }
-
-                var scene = engine.scenes[0];
-
-                if (scene.activeCamera || scene.activeCameras.length > 0) {
-                    scene.render();
-                }
-            });
-
-            var scene;
-            if (code.indexOf("createScene") !== -1) { // createScene
-                eval(code);
-                scene = createScene();
-                if (!scene) {
-                    showError("createScene function must return a scene.");
-                    return;
-                }
-
-                zipCode = code + "\r\n\r\nvar scene = createScene();";
-            } else if (code.indexOf("CreateScene") !== -1) { // CreateScene
-                eval(code);
-                scene = CreateScene();
-                if (!scene) {
-                    showError("CreateScene function must return a scene.");
-                    return;
-                }
-
-                zipCode = code + "\r\n\r\nvar scene = CreateScene();";
-            } else if (code.indexOf("createscene") !== -1) { // createscene
-                eval(code);
-                scene = createscene();
-                if (!scene) {
-                    showError("createscene function must return a scene.");
-                    return;
-                }
-
-                zipCode = code + "\r\n\r\nvar scene = createscene();";
-            } else { // Direct code
-                scene = new BABYLON.Scene(engine);
-                eval("runScript = function(scene, canvas) {" + code + "}");
-                runScript(scene, canvas);
-
-                zipCode = "var scene = new BABYLON.Scene(engine);\r\n\r\n" + code;
-            }
-
-        } catch (e) {
-            // showError(e.message);
-        }
-    };
-    window.addEventListener("resize", function () {
-        if (engine) {
-            engine.resize();
-        }
-    });
-
-    // UI
-
-    var cleanHash = function () {
-        var splits = decodeURIComponent(location.hash.substr(1)).split("#");
-
-        if (splits.length > 2) {
-            splits.splice(2, splits.length - 2);
-        }
-
-        location.hash = splits.join("#");
-    };
-
-    var checkHash = function () {
-        if (location.hash) {
-            cleanHash();
-
-            try {
-                var xmlHttp = new XMLHttpRequest();
-                xmlHttp.onreadystatechange = function () {
-                    if (xmlHttp.readyState === 4) {
-                        if (xmlHttp.status === 200) {
-                            var snippetCode = JSON.parse(JSON.parse(xmlHttp.responseText)[0].jsonPayload).code;
-                            compileAndRun(snippetCode);
-                        }
-                    }
-                };
-
-                var hash = location.hash.substr(1);
-                currentSnippetToken = hash.split("#")[0];
-                if(!hash.split("#")[1]) hash += "#0";
-
-                xmlHttp.open("GET", snippetUrl + "/" + hash.replace("#", "/"));
-                xmlHttp.send();
-            } catch (e) {
-
-            }
-        }
-    };
-
-    checkHash();
-
-})();

+ 0 - 77
Playground/perf.html

@@ -1,77 +0,0 @@
-<!DOCTYPE html>
-<html>
-
-<head>
-    <title>Babylon.js Playground</title>
-    <link rel="shortcut icon" href="https://www.babylonjs.com/img/favicon/favicon.ico">
-	<link rel="apple-touch-icon" sizes="57x57" href="https://www.babylonjs.com/img/favicon/apple-icon-57x57.png">
-	<link rel="apple-touch-icon" sizes="60x60" href="https://www.babylonjs.com/img/favicon/apple-icon-60x60.png">
-	<link rel="apple-touch-icon" sizes="72x72" href="https://www.babylonjs.com/img/favicon/apple-icon-72x72.png">
-	<link rel="apple-touch-icon" sizes="76x76" href="https://www.babylonjs.com/img/favicon/apple-icon-76x76.png">
-	<link rel="apple-touch-icon" sizes="114x114" href="https://www.babylonjs.com/img/favicon/apple-icon-114x114.png">
-	<link rel="apple-touch-icon" sizes="120x120" href="https://www.babylonjs.com/img/favicon/apple-icon-120x120.png">
-	<link rel="apple-touch-icon" sizes="144x144" href="https://www.babylonjs.com/img/favicon/apple-icon-144x144.png">
-	<link rel="apple-touch-icon" sizes="152x152" href="https://www.babylonjs.com/img/favicon/apple-icon-152x152.png">
-	<link rel="apple-touch-icon" sizes="180x180" href="https://www.babylonjs.com/img/favicon/apple-icon-180x180.png">
-	<link rel="icon" type="image/png" sizes="192x192"  href="https://www.babylonjs.com/img/favicon/android-icon-192x192.png">
-	<link rel="icon" type="image/png" sizes="32x32" href="https://www.babylonjs.com/img/favicon/favicon-32x32.png">
-	<link rel="icon" type="image/png" sizes="96x96" href="https://www.babylonjs.com/img/favicon/favicon-96x96.png">
-	<link rel="icon" type="image/png" sizes="16x16" href="https://www.babylonjs.com/img/favicon/favicon-16x16.png">
-	<link rel="manifest" href="https://www.babylonjs.com/img/favicon/manifest.json">
-	<meta name="msapplication-TileColor" content="#ffffff">
-	<meta name="msapplication-TileImage" content="https://www.babylonjs.com/img/favicon/ms-icon-144x144.png">
-	<meta name="msapplication-config" content="https://www.babylonjs.com/img/favicon/browserconfig.xml">
-	<meta name="theme-color" content="#ffffff">
-
-    <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
-    <!-- Babylon.js -->
-    <script src="https://preview.babylonjs.com/cannon.js"></script>
-    <script src="https://preview.babylonjs.com/Oimo.js"></script>
-    <script src="https://preview.babylonjs.com/babylon.js"></script>    
-    <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
-
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.fireMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.waterMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.lavaMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.normalMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.skyMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.triPlanarMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.terrainMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gradientMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.furMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.gridMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.shadowOnlyMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.customMaterial.min.js"></script>
-    <script src="https://preview.babylonjs.com/materialsLibrary/babylon.cellMaterial.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.brickProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.cloudProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.fireProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.grassProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.marbleProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.roadProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.starfieldProceduralTexture.min.js"></script>
-    <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylon.woodProceduralTexture.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.asciiArtPostProcess.min.js"></script>
-    <script src="https://preview.babylonjs.com/postProcessesLibrary/babylon.digitalRainPostProcess.min.js"></script>
-
-    <script src="https://preview.babylonjs.com/loaders/babylon.glTFFileLoader.js"></script>
-    <script src="https://preview.babylonjs.com/loaders/babylon.objFileLoader.js"></script>
-    <script src="https://preview.babylonjs.com/loaders/babylon.stlFileLoader.js"></script>
-
-    <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
-    
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/ClonerSystem/src/babylonx.cloner.js"></script>    
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/canvas2D/dist/preview%20release/babylon.canvas2d.min.js"></script>
-    <script src="https://rawgit.com/BabylonJS/Extensions/master/CompoundShader/src/babylonx.CompoundShader.js"></script>
-    <link href="frame.css" rel="stylesheet" />
-</head>
-
-<body>
-    <canvas touch-action="none" id="renderCanvas"></canvas>
-    <script src="https://code.jquery.com/jquery.js"></script>
-    <script src="/js/perf.js"></script>
-</body>
-
-</html>

+ 19 - 11
Tools/Gulp/config.json

@@ -27,16 +27,19 @@
         "minimal": ["standardMaterial", "freeCamera", "hemisphericLight"],
         "minimalWithBuilder": ["meshBuilder", "standardMaterial", "freeCamera", "hemisphericLight"],
         "minimalGLTFViewer": [
-                "animations", "arcRotateCamera", "additionalTextures", "textureFormats",
-                "shadows", "pointLight", "directionalLight", "spotLight",
-                "multiMaterial", "pbrMaterial",
-                "meshBuilder", "layer",
-                "additionalPostProcess_blur", "additionalPostProcess_fxaa", "additionalPostProcess_highlights", 
-                "additionalPostProcess_imageProcessing", "colorCurves", "defaultRenderingPipeline", "imageProcessing",
-                "debug", "textureTools", "hdr",
-                "loader",
+                "standardMaterial", "pbrMaterial", "freeCamera", "arcRotateCamera", "hemisphericLight", 
+                "pointLight", "directionalLight", "spotLight", "animations", "actions", "sprites", "picking", "collisions",
+                "particles", "solidParticles", "additionalMeshes", "meshBuilder", "audio", "additionalTextures", "shadows",
+                "loader", "userData", "offline", "fresnel", "multiMaterial", "touchCamera", "procedural", "gamepad",
+                "additionalCameras", "postProcesses", "renderingPipeline", "additionalRenderingPipeline", "defaultRenderingPipeline",
+                "depthRenderer", "geometryBufferRenderer", "additionalPostProcesses",
+                "additionalPostProcess_blur", "additionalPostProcess_fxaa", "additionalPostProcess_imageProcessing",
+                "bones", "hdr", "polygonMesh", "csg", "lensFlares", "physics", "textureFormats", "debug", "morphTargets",
+                "colorCurves", "octrees", "simd", "vr", "virtualJoystick", "optimizations", "highlights", "assetsManager",
+                "mapTexture", "dynamicFloatArray",
+                "imageProcessing", "serialization", "probes", "layer", "textureTools", "cameraBehaviors",
                 "materialsLibrary/babylon.gridMaterial.js",
-                "loaders/babylon.glTFFileLoader.js", "cameraBehaviors", "morphTargets"
+                "loaders/babylon.glTFFileLoader.js"
         ],
         "distributed": ["minimalGLTFViewer"]
     },
@@ -84,6 +87,9 @@
                 "../../src/Mesh/babylon.geometry.js",
                 "../../src/PostProcess/babylon.postProcessManager.js",
                 "../../src/Tools/babylon.performanceMonitor.js"
+            ],
+            "shaderIncludes": [
+                "depthPrePass"
             ]
         },         
         "particles" : 
@@ -587,10 +593,11 @@
                 "geometry.fragment"
             ],
             "shaderIncludes": [
+                "mrtFragmentDeclaration",
                 "bones300Declaration",
                 "instances300Declaration",
                 "instancesVertex",
-                "bonesVertex"
+                "bonesVertex"               
             ]
         },
         "postProcesses" : 
@@ -1441,7 +1448,8 @@
                     "../../gui/src/controls/image.ts",
                     "../../gui/src/controls/button.ts",
                     "../../gui/src/controls/colorPicker.ts",
-                    "../../gui/src/controls/inputText.ts"
+                    "../../gui/src/controls/inputText.ts",
+                    "../../gui/src/controls/virtualKeyboard.ts"
                 ],
                 "output": "babylon.gui.js",
                 "buildAsModule": "true",

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


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


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


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


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


File diff suppressed because it is too large
+ 2137 - 2116
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


File diff suppressed because it is too large
+ 51 - 37
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


File diff suppressed because it is too large
+ 37237 - 17140
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js


File diff suppressed because it is too large
+ 2137 - 2116
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts


+ 45 - 0
dist/preview release/gui/babylon.gui.d.ts

@@ -168,6 +168,7 @@ declare module BABYLON.GUI {
         private _doNotRender;
         isHitTestVisible: boolean;
         isPointerBlocker: boolean;
+        isFocusInvisible: boolean;
         protected _linkOffsetX: ValueAndUnit;
         protected _linkOffsetY: ValueAndUnit;
         readonly typeName: string;
@@ -258,6 +259,7 @@ declare module BABYLON.GUI {
         forcePointerUp(): void;
         _processObservables(type: number, x: number, y: number): boolean;
         private _prepareFont();
+        dispose(): void;
         private static _HORIZONTAL_ALIGNMENT_LEFT;
         private static _HORIZONTAL_ALIGNMENT_RIGHT;
         private static _HORIZONTAL_ALIGNMENT_CENTER;
@@ -309,6 +311,7 @@ declare module BABYLON.GUI {
         _processPicking(x: number, y: number, type: number): boolean;
         protected _clipForChildren(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        dispose(): void;
     }
 }
 
@@ -607,6 +610,10 @@ declare module BABYLON.GUI {
         private _blinkIsEven;
         private _cursorOffset;
         private _scrollLeft;
+        promptMessage: string;
+        onTextChangedObservable: Observable<InputText>;
+        onFocusObservable: Observable<InputText>;
+        onBlurObservable: Observable<InputText>;
         maxWidth: string | number;
         margin: string;
         autoStretchWidth: boolean;
@@ -618,9 +625,47 @@ declare module BABYLON.GUI {
         onBlur(): void;
         onFocus(): void;
         protected _getTypeName(): string;
+        processKey(keyCode: number, key?: string): void;
         processKeyboard(evt: KeyboardEvent): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _onPointerDown(coordinates: Vector2): boolean;
         protected _onPointerUp(coordinates: Vector2): void;
+        dispose(): void;
+    }
+}
+
+
+declare module BABYLON.GUI {
+    class KeyPropertySet {
+        width?: string;
+        height?: string;
+        paddingLeft?: string;
+        paddingRight?: string;
+        paddingTop?: string;
+        paddingBottom?: string;
+        color?: string;
+        background?: string;
+    }
+    class VirtualKeyboard extends StackPanel {
+        onKeyPressObservable: Observable<string>;
+        defaultButtonWidth: string;
+        defaultButtonHeight: string;
+        defaultButtonPaddingLeft: string;
+        defaultButtonPaddingRight: string;
+        defaultButtonPaddingTop: string;
+        defaultButtonPaddingBottom: string;
+        defaultButtonColor: string;
+        defaultButtonBackground: string;
+        protected _getTypeName(): string;
+        private _createKey(key, propertySet?);
+        addKeysRow(keys: Array<string>, propertySets?: Array<KeyPropertySet>): void;
+        private _connectedInputText;
+        private _onFocusObserver;
+        private _onBlurObserver;
+        private _onKeyPressObserver;
+        readonly connectedInputText: InputText;
+        connect(input: InputText): void;
+        disconnect(): void;
+        static CreateDefaultLayout(): VirtualKeyboard;
     }
 }

+ 178 - 10
dist/preview release/gui/babylon.gui.js

@@ -182,6 +182,7 @@ var BABYLON;
                     this._layerToDispose.dispose();
                     this._layerToDispose = null;
                 }
+                this._rootContainer.dispose();
                 _super.prototype.dispose.call(this);
             };
             AdvancedDynamicTexture.prototype._onResize = function () {
@@ -293,6 +294,9 @@ var BABYLON;
                 // Focus management
                 if (this._focusedControl) {
                     if (this._focusedControl !== this._lastPickedControl) {
+                        if (this._lastPickedControl.isFocusInvisible) {
+                            return;
+                        }
                         this.focusedControl = null;
                     }
                 }
@@ -726,6 +730,7 @@ var BABYLON;
                 this._doNotRender = false;
                 this.isHitTestVisible = true;
                 this.isPointerBlocker = false;
+                this.isFocusInvisible = false;
                 this._linkOffsetX = new GUI.ValueAndUnit(0);
                 this._linkOffsetY = new GUI.ValueAndUnit(0);
                 /**
@@ -1482,6 +1487,14 @@ var BABYLON;
                 this._font = this._fontSize.getValue(this._host) + "px " + this._fontFamily;
                 this._fontOffset = Control._GetFontOffset(this._font);
             };
+            Control.prototype.dispose = function () {
+                this.onDirtyObservable.clear();
+                this.onPointerDownObservable.clear();
+                this.onPointerEnterObservable.clear();
+                this.onPointerMoveObservable.clear();
+                this.onPointerOutObservable.clear();
+                this.onPointerUpObservable.clear();
+            };
             Object.defineProperty(Control, "HORIZONTAL_ALIGNMENT_LEFT", {
                 get: function () {
                     return Control._HORIZONTAL_ALIGNMENT_LEFT;
@@ -1681,6 +1694,7 @@ var BABYLON;
                     return this;
                 }
                 control._link(this, this._host);
+                control._markAllAsDirty();
                 this._reOrderControl(control);
                 this._markAsDirty();
                 return this;
@@ -1770,6 +1784,13 @@ var BABYLON;
                 _super.prototype._additionalProcessing.call(this, parentMeasure, context);
                 this._measureForChildren.copyFrom(this._currentMeasure);
             };
+            Container.prototype.dispose = function () {
+                _super.prototype.dispose.call(this);
+                for (var _i = 0, _a = this._children; _i < _a.length; _i++) {
+                    var control = _a[_i];
+                    control.dispose();
+                }
+            };
             return Container;
         }(GUI.Control));
         GUI.Container = Container;
@@ -3762,6 +3783,10 @@ var BABYLON;
                 _this._isFocused = false;
                 _this._blinkIsEven = false;
                 _this._cursorOffset = 0;
+                _this.promptMessage = "Please enter text:";
+                _this.onTextChangedObservable = new BABYLON.Observable();
+                _this.onFocusObservable = new BABYLON.Observable();
+                _this.onBlurObservable = new BABYLON.Observable();
                 _this.text = text;
                 return _this;
             }
@@ -3861,6 +3886,7 @@ var BABYLON;
                     }
                     this._text = value;
                     this._markAsDirty();
+                    this.onTextChangedObservable.notifyObservers(this);
                 },
                 enumerable: true,
                 configurable: true
@@ -3871,6 +3897,7 @@ var BABYLON;
                 this._cursorOffset = 0;
                 clearTimeout(this._blinkTimeout);
                 this._markAsDirty();
+                this.onBlurObservable.notifyObservers(this);
             };
             InputText.prototype.onFocus = function () {
                 this._scrollLeft = null;
@@ -3878,13 +3905,19 @@ var BABYLON;
                 this._blinkIsEven = false;
                 this._cursorOffset = 0;
                 this._markAsDirty();
+                this.onFocusObservable.notifyObservers(this);
+                if (navigator.userAgent.indexOf("Mobile") !== -1) {
+                    this.text = prompt(this.promptMessage);
+                    this._host.focusedControl = null;
+                    return;
+                }
             };
             InputText.prototype._getTypeName = function () {
                 return "InputText";
             };
-            InputText.prototype.processKeyboard = function (evt) {
+            InputText.prototype.processKey = function (keyCode, key) {
                 // Specific cases
-                switch (evt.keyCode) {
+                switch (keyCode) {
                     case 8:// BACKSPACE
                         if (this._text && this._text.length > 0) {
                             if (this._cursorOffset === 0) {
@@ -3936,21 +3969,25 @@ var BABYLON;
                         return;
                 }
                 // Printable characters
-                if ((evt.keyCode === 32) ||
-                    (evt.keyCode > 47 && evt.keyCode < 58) ||
-                    (evt.keyCode > 64 && evt.keyCode < 91) ||
-                    (evt.keyCode > 185 && evt.keyCode < 193) ||
-                    (evt.keyCode > 218 && evt.keyCode < 223) ||
-                    (evt.keyCode > 95 && evt.keyCode < 112)) {
+                if ((keyCode === -1) ||
+                    (keyCode === 32) ||
+                    (keyCode > 47 && keyCode < 58) ||
+                    (keyCode > 64 && keyCode < 91) ||
+                    (keyCode > 185 && keyCode < 193) ||
+                    (keyCode > 218 && keyCode < 223) ||
+                    (keyCode > 95 && keyCode < 112)) {
                     if (this._cursorOffset === 0) {
-                        this.text += evt.key;
+                        this.text += key;
                     }
                     else {
                         var insertPosition = this._text.length - this._cursorOffset;
-                        this.text = this._text.slice(0, insertPosition) + evt.key + this._text.slice(insertPosition);
+                        this.text = this._text.slice(0, insertPosition) + key + this._text.slice(insertPosition);
                     }
                 }
             };
+            InputText.prototype.processKeyboard = function (evt) {
+                this.processKey(evt.keyCode, evt.key);
+            };
             InputText.prototype._draw = function (parentMeasure, context) {
                 var _this = this;
                 context.save();
@@ -4042,8 +4079,139 @@ var BABYLON;
             InputText.prototype._onPointerUp = function (coordinates) {
                 _super.prototype._onPointerUp.call(this, coordinates);
             };
+            InputText.prototype.dispose = function () {
+                _super.prototype.dispose.call(this);
+                this.onBlurObservable.clear();
+                this.onFocusObservable.clear();
+                this.onTextChangedObservable.clear();
+            };
             return InputText;
         }(GUI.Control));
         GUI.InputText = InputText;
     })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
 })(BABYLON || (BABYLON = {}));
+
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = Object.setPrototypeOf ||
+        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
+    return function (d, b) {
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+var BABYLON;
+(function (BABYLON) {
+    var GUI;
+    (function (GUI) {
+        var KeyPropertySet = (function () {
+            function KeyPropertySet() {
+            }
+            return KeyPropertySet;
+        }());
+        GUI.KeyPropertySet = KeyPropertySet;
+        var VirtualKeyboard = (function (_super) {
+            __extends(VirtualKeyboard, _super);
+            function VirtualKeyboard() {
+                var _this = _super !== null && _super.apply(this, arguments) || this;
+                _this.onKeyPressObservable = new BABYLON.Observable();
+                _this.defaultButtonWidth = "40px";
+                _this.defaultButtonHeight = "40px";
+                _this.defaultButtonPaddingLeft = "2px";
+                _this.defaultButtonPaddingRight = "2px";
+                _this.defaultButtonPaddingTop = "2px";
+                _this.defaultButtonPaddingBottom = "2px";
+                _this.defaultButtonColor = "#DDD";
+                _this.defaultButtonBackground = "#070707";
+                return _this;
+            }
+            VirtualKeyboard.prototype._getTypeName = function () {
+                return "VirtualKeyboard";
+            };
+            VirtualKeyboard.prototype._createKey = function (key, propertySet) {
+                var _this = this;
+                var button = GUI.Button.CreateSimpleButton(key, key);
+                button.width = propertySet && propertySet.width ? propertySet.width : this.defaultButtonWidth;
+                button.height = propertySet && propertySet.height ? propertySet.height : this.defaultButtonHeight;
+                button.color = propertySet && propertySet.color ? propertySet.color : this.defaultButtonColor;
+                button.background = propertySet && propertySet.background ? propertySet.background : this.defaultButtonBackground;
+                button.paddingLeft = propertySet && propertySet.paddingLeft ? propertySet.paddingLeft : this.defaultButtonPaddingLeft;
+                button.paddingRight = propertySet && propertySet.paddingRight ? propertySet.paddingRight : this.defaultButtonPaddingRight;
+                button.paddingTop = propertySet && propertySet.paddingTop ? propertySet.paddingTop : this.defaultButtonPaddingTop;
+                button.paddingBottom = propertySet && propertySet.paddingBottom ? propertySet.paddingBottom : this.defaultButtonPaddingBottom;
+                button.thickness = 0;
+                button.isFocusInvisible = true;
+                button.onPointerUpObservable.add(function () {
+                    _this.onKeyPressObservable.notifyObservers(key);
+                });
+                return button;
+            };
+            VirtualKeyboard.prototype.addKeysRow = function (keys, propertySets) {
+                var panel = new GUI.StackPanel();
+                panel.isVertical = false;
+                panel.isFocusInvisible = true;
+                for (var i = 0; i < keys.length; i++) {
+                    var properties = null;
+                    if (propertySets && propertySets.length === keys.length) {
+                        properties = propertySets[i];
+                    }
+                    panel.addControl(this._createKey(keys[i], properties));
+                }
+                this.addControl(panel);
+            };
+            Object.defineProperty(VirtualKeyboard.prototype, "connectedInputText", {
+                get: function () {
+                    return this._connectedInputText;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            VirtualKeyboard.prototype.connect = function (input) {
+                var _this = this;
+                this.isVisible = false;
+                this._connectedInputText = input;
+                // Events hooking
+                this._onFocusObserver = input.onFocusObservable.add(function () {
+                    _this.isVisible = true;
+                });
+                this._onBlurObserver = input.onBlurObservable.add(function () {
+                    _this.isVisible = false;
+                });
+                this._onKeyPressObserver = this.onKeyPressObservable.add(function (key) {
+                    switch (key) {
+                        case "\u2190":
+                            _this._connectedInputText.processKey(8);
+                            return;
+                        case "\u21B5":
+                            _this._connectedInputText.processKey(13);
+                            return;
+                    }
+                    _this._connectedInputText.processKey(-1, key);
+                });
+            };
+            VirtualKeyboard.prototype.disconnect = function () {
+                if (!this._connectedInputText) {
+                    return;
+                }
+                this._connectedInputText.onFocusObservable.remove(this._onFocusObserver);
+                this._connectedInputText.onBlurObservable.remove(this._onBlurObserver);
+                this.onKeyPressObservable.remove(this._onKeyPressObserver);
+                this._connectedInputText = null;
+            };
+            // Statics
+            VirtualKeyboard.CreateDefaultLayout = function () {
+                var returnValue = new VirtualKeyboard();
+                returnValue.addKeysRow(["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "\u2190"]);
+                returnValue.addKeysRow(["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"]);
+                returnValue.addKeysRow(["a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "\u21B5"]);
+                returnValue.addKeysRow(["z", "x", "c", "v", "b", "n", "m", ",", ".", "/"]);
+                returnValue.addKeysRow([" "], [{ width: "200px" }]);
+                return returnValue;
+            };
+            return VirtualKeyboard;
+        }(GUI.StackPanel));
+        GUI.VirtualKeyboard = VirtualKeyboard;
+    })(GUI = BABYLON.GUI || (BABYLON.GUI = {}));
+})(BABYLON || (BABYLON = {}));

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


+ 45 - 0
dist/preview release/gui/babylon.gui.module.d.ts

@@ -168,6 +168,7 @@ declare module BABYLON.GUI {
         private _doNotRender;
         isHitTestVisible: boolean;
         isPointerBlocker: boolean;
+        isFocusInvisible: boolean;
         protected _linkOffsetX: ValueAndUnit;
         protected _linkOffsetY: ValueAndUnit;
         readonly typeName: string;
@@ -258,6 +259,7 @@ declare module BABYLON.GUI {
         forcePointerUp(): void;
         _processObservables(type: number, x: number, y: number): boolean;
         private _prepareFont();
+        dispose(): void;
         private static _HORIZONTAL_ALIGNMENT_LEFT;
         private static _HORIZONTAL_ALIGNMENT_RIGHT;
         private static _HORIZONTAL_ALIGNMENT_CENTER;
@@ -309,6 +311,7 @@ declare module BABYLON.GUI {
         _processPicking(x: number, y: number, type: number): boolean;
         protected _clipForChildren(context: CanvasRenderingContext2D): void;
         protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
+        dispose(): void;
     }
 }
 
@@ -607,6 +610,10 @@ declare module BABYLON.GUI {
         private _blinkIsEven;
         private _cursorOffset;
         private _scrollLeft;
+        promptMessage: string;
+        onTextChangedObservable: Observable<InputText>;
+        onFocusObservable: Observable<InputText>;
+        onBlurObservable: Observable<InputText>;
         maxWidth: string | number;
         margin: string;
         autoStretchWidth: boolean;
@@ -618,10 +625,48 @@ declare module BABYLON.GUI {
         onBlur(): void;
         onFocus(): void;
         protected _getTypeName(): string;
+        processKey(keyCode: number, key?: string): void;
         processKeyboard(evt: KeyboardEvent): void;
         _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void;
         protected _onPointerDown(coordinates: Vector2): boolean;
         protected _onPointerUp(coordinates: Vector2): void;
+        dispose(): void;
+    }
+}
+
+/// <reference path="../../../dist/preview release/babylon.d.ts" />
+declare module BABYLON.GUI {
+    class KeyPropertySet {
+        width?: string;
+        height?: string;
+        paddingLeft?: string;
+        paddingRight?: string;
+        paddingTop?: string;
+        paddingBottom?: string;
+        color?: string;
+        background?: string;
+    }
+    class VirtualKeyboard extends StackPanel {
+        onKeyPressObservable: Observable<string>;
+        defaultButtonWidth: string;
+        defaultButtonHeight: string;
+        defaultButtonPaddingLeft: string;
+        defaultButtonPaddingRight: string;
+        defaultButtonPaddingTop: string;
+        defaultButtonPaddingBottom: string;
+        defaultButtonColor: string;
+        defaultButtonBackground: string;
+        protected _getTypeName(): string;
+        private _createKey(key, propertySet?);
+        addKeysRow(keys: Array<string>, propertySets?: Array<KeyPropertySet>): void;
+        private _connectedInputText;
+        private _onFocusObserver;
+        private _onBlurObserver;
+        private _onKeyPressObserver;
+        readonly connectedInputText: InputText;
+        connect(input: InputText): void;
+        disconnect(): void;
+        static CreateDefaultLayout(): VirtualKeyboard;
     }
 }
 

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


+ 1 - 0
dist/preview release/materialsLibrary/babylon.waterMaterial.js

@@ -25,6 +25,7 @@ var BABYLON;
             _this.REFLECTION = false;
             _this.CLIPPLANE = false;
             _this.ALPHATEST = false;
+            _this.DEPTHPREPASS = false;
             _this.POINTSIZE = false;
             _this.FOG = false;
             _this.NORMAL = false;

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


+ 2 - 0
dist/preview release/what's new.md

@@ -11,6 +11,8 @@
  - Framing ([deltakosh](https://github.com/deltakosh))
  - Bouncing ([deltakosh](https://github.com/deltakosh))
 - New InputText for Babylon.GUI. [Doc here](http://doc.babylonjs.com/overviews/gui#inputtext) ([deltakosh](https://github.com/deltakosh))
+- New VirtualKeyboard for Babylon.GUI. [Doc here](http://doc.babylonjs.com/overviews/gui#virtualkeyboard) ([deltakosh](https://github.com/deltakosh) / [adam](https://github.com/abow))
+- Added support for depth pre-pass rendering. [Doc here](http://doc.babylonjs.com/tutorials/transparency_and_how_meshes_are_rendered#depth-pre-pass-meshes) ([deltakosh](https://github.com/deltakosh))
 
 ## Updates
 - New `camera.storeState()` and `camera.restoreState()` functions to store / restore cameras position / rotation / fov. (Doc here)[http://doc.babylonjs.com/tutorials/cameras#state] ([deltakosh](https://github.com/deltakosh))

+ 6 - 0
gui/src/advancedDynamicTexture.ts

@@ -193,6 +193,8 @@ module BABYLON.GUI {
                 this._layerToDispose = null;
             }
 
+            this._rootContainer.dispose();
+
             super.dispose();
         }
 
@@ -328,6 +330,10 @@ module BABYLON.GUI {
             // Focus management
             if (this._focusedControl) {
                 if (this._focusedControl !== (<any>this._lastPickedControl)) {
+                    if (this._lastPickedControl.isFocusInvisible) {
+                        return;
+                    }
+
                     this.focusedControl = null;
                 }
             }

+ 10 - 0
gui/src/controls/container.ts

@@ -63,6 +63,8 @@ module BABYLON.GUI {
             }
             control._link(this, this._host);
 
+            control._markAllAsDirty();
+
             this._reOrderControl(control);
 
             this._markAsDirty();
@@ -176,5 +178,13 @@ module BABYLON.GUI {
 
             this._measureForChildren.copyFrom(this._currentMeasure);
         }
+
+        public dispose() {
+            super.dispose();
+
+            for (var control of this._children) {
+                control.dispose();
+            }
+        }
     }    
 }

+ 10 - 0
gui/src/controls/control.ts

@@ -47,6 +47,7 @@ module BABYLON.GUI {
 
         public isHitTestVisible = true;
         public isPointerBlocker = false;
+        public isFocusInvisible = false;
 
         protected _linkOffsetX = new ValueAndUnit(0);
         protected _linkOffsetY = new ValueAndUnit(0);
@@ -859,6 +860,15 @@ module BABYLON.GUI {
             this._fontOffset = Control._GetFontOffset(this._font);
         }
 
+        public dispose() {
+            this.onDirtyObservable.clear();
+            this.onPointerDownObservable.clear();
+            this.onPointerEnterObservable.clear();
+            this.onPointerMoveObservable.clear();
+            this.onPointerOutObservable.clear();
+            this.onPointerUpObservable.clear();
+        }
+
         // Statics
         private static _HORIZONTAL_ALIGNMENT_LEFT = 0;
         private static _HORIZONTAL_ALIGNMENT_RIGHT = 1;

+ 41 - 10
gui/src/controls/inputText.ts

@@ -15,6 +15,12 @@ module BABYLON.GUI {
         private _cursorOffset = 0;        
         private _scrollLeft: number;
 
+        public promptMessage = "Please enter text:";
+
+        public onTextChangedObservable = new Observable<InputText>();
+        public onFocusObservable = new Observable<InputText>();
+        public onBlurObservable = new Observable<InputText>();
+
         public get maxWidth(): string | number {
             return this._maxWidth.toString(this._host);
         }
@@ -105,6 +111,8 @@ module BABYLON.GUI {
             }
             this._text = value;
             this._markAsDirty();
+
+            this.onTextChangedObservable.notifyObservers(this);
         }
 
         constructor(public name?: string, text: string = "") {
@@ -119,6 +127,8 @@ module BABYLON.GUI {
             this._cursorOffset = 0;
             clearTimeout(this._blinkTimeout);
             this._markAsDirty();
+
+            this.onBlurObservable.notifyObservers(this);
         }
 
         public onFocus(): void {
@@ -127,15 +137,23 @@ module BABYLON.GUI {
             this._blinkIsEven = false;
             this._cursorOffset = 0;
             this._markAsDirty();
+
+            this.onFocusObservable.notifyObservers(this);
+
+            if (navigator.userAgent.indexOf("Mobile") !== -1) {
+                this.text = prompt(this.promptMessage);
+                this._host.focusedControl = null;
+                return;
+            }
         }
 
         protected _getTypeName(): string {
             return "InputText";
         }
 
-        public processKeyboard(evt: KeyboardEvent): void {
+        public processKey(keyCode: number, key?: string) {
             // Specific cases
-            switch (evt.keyCode) {
+            switch (keyCode) {
                 case 8: // BACKSPACE
                     if (this._text && this._text.length > 0) {
                         if (this._cursorOffset === 0) {
@@ -188,22 +206,27 @@ module BABYLON.GUI {
 
             // Printable characters
             if (
-                (evt.keyCode === 32) ||                         // Space
-                (evt.keyCode > 47 && evt.keyCode < 58) ||       // Numbers
-                (evt.keyCode > 64 && evt.keyCode < 91) ||       // Letters
-                (evt.keyCode > 185 && evt.keyCode < 193) ||     // Special characters
-                (evt.keyCode > 218  && evt.keyCode < 223) ||    // Special characters
-                (evt.keyCode > 95 && evt.keyCode < 112)) {      // Numpad
+                (keyCode === -1) ||                     // Direct access
+                (keyCode === 32) ||                     // Space
+                (keyCode > 47 && keyCode < 58) ||       // Numbers
+                (keyCode > 64 && keyCode < 91) ||       // Letters
+                (keyCode > 185 && keyCode < 193) ||     // Special characters
+                (keyCode > 218  && keyCode < 223) ||    // Special characters
+                (keyCode > 95 && keyCode < 112)) {      // Numpad
                     if (this._cursorOffset === 0) {
-                        this.text += evt.key;
+                        this.text += key;
                     } else {
                         let insertPosition = this._text.length - this._cursorOffset;
 
-                        this.text = this._text.slice(0, insertPosition) + evt.key + this._text.slice(insertPosition);
+                        this.text = this._text.slice(0, insertPosition) + key + this._text.slice(insertPosition);
                     }
                 }
         }
 
+        public processKeyboard(evt: KeyboardEvent): void {
+            this.processKey(evt.keyCode, evt.key);
+        }
+
         public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
             context.save();
 
@@ -312,5 +335,13 @@ module BABYLON.GUI {
         protected _onPointerUp(coordinates: Vector2): void {
             super._onPointerUp(coordinates);
         }  
+
+        public dispose() {
+            super.dispose();
+
+            this.onBlurObservable.clear();
+            this.onFocusObservable.clear();
+            this.onTextChangedObservable.clear();
+        }
     }
 }

+ 136 - 0
gui/src/controls/virtualKeyboard.ts

@@ -0,0 +1,136 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+
+    export class KeyPropertySet {
+        width?: string;
+        height?: string;
+        paddingLeft?: string;
+        paddingRight?: string;
+        paddingTop?: string;
+        paddingBottom?: string;
+        color?: string;
+        background?: string;
+    }
+
+    export class VirtualKeyboard extends StackPanel {
+        public onKeyPressObservable = new Observable<string>();
+
+        public defaultButtonWidth = "40px";
+        public defaultButtonHeight = "40px";
+
+        public defaultButtonPaddingLeft= "2px";
+        public defaultButtonPaddingRight = "2px";
+        public defaultButtonPaddingTop = "2px";
+        public defaultButtonPaddingBottom = "2px";    
+        
+        public defaultButtonColor = "#DDD";
+        public defaultButtonBackground = "#070707";    
+        
+        protected _getTypeName(): string {
+            return "VirtualKeyboard";
+        }
+
+        private _createKey(key: string, propertySet?: KeyPropertySet) {
+            var button = Button.CreateSimpleButton(key, key);
+            
+           
+            button.width = propertySet && propertySet.width ? propertySet.width : this.defaultButtonWidth;
+            button.height = propertySet && propertySet.height ? propertySet.height : this.defaultButtonHeight;
+            button.color = propertySet && propertySet.color ? propertySet.color : this.defaultButtonColor;
+            button.background = propertySet && propertySet.background ? propertySet.background : this.defaultButtonBackground;
+            button.paddingLeft = propertySet && propertySet.paddingLeft ? propertySet.paddingLeft : this.defaultButtonPaddingLeft;
+            button.paddingRight = propertySet && propertySet.paddingRight ? propertySet.paddingRight : this.defaultButtonPaddingRight;
+            button.paddingTop = propertySet && propertySet.paddingTop ? propertySet.paddingTop : this.defaultButtonPaddingTop;
+            button.paddingBottom = propertySet && propertySet.paddingBottom ? propertySet.paddingBottom : this.defaultButtonPaddingBottom;
+        
+            button.thickness = 0;
+            button.isFocusInvisible = true;
+        
+            button.onPointerUpObservable.add(() => {
+                this.onKeyPressObservable.notifyObservers(key);
+            });
+    
+            return button;
+        }
+
+        public addKeysRow(keys: Array<string>, propertySets?: Array<KeyPropertySet>): void {
+            let panel = new StackPanel();
+            panel.isVertical = false;
+            panel.isFocusInvisible = true;
+        
+            for(var i = 0; i < keys.length; i++) {
+                let properties = null;
+
+                if (propertySets && propertySets.length === keys.length) {
+                    properties = propertySets[i];
+                }
+
+                panel.addControl(this._createKey(keys[i], properties));
+            }
+        
+            this.addControl(panel);
+        }
+
+        private _connectedInputText: InputText;
+        private _onFocusObserver: Observer<InputText>;
+        private _onBlurObserver: Observer<InputText>;
+        private _onKeyPressObserver: Observer<string>;
+
+        public get connectedInputText(): InputText {
+            return this._connectedInputText;
+        }
+
+        public connect(input: InputText): void {
+            this.isVisible = false;
+            this._connectedInputText = input;
+            
+            // Events hooking
+            this._onFocusObserver = input.onFocusObservable.add(() => {
+                this.isVisible = true;
+            });
+    
+            this._onBlurObserver = input.onBlurObservable.add(() => {
+                this.isVisible = false;
+            });		
+
+            this._onKeyPressObserver = this.onKeyPressObservable.add((key) => {
+                switch (key) {
+                    case "\u2190":
+                        this._connectedInputText.processKey(8);
+                        return;
+                    case "\u21B5":
+                        this._connectedInputText.processKey(13);
+                        return;                        
+                }
+
+                this._connectedInputText.processKey(-1, key);
+            });
+        }
+
+        public disconnect(): void {
+            if (!this._connectedInputText) {
+                return;
+            }
+
+            this._connectedInputText.onFocusObservable.remove(this._onFocusObserver);
+            this._connectedInputText.onBlurObservable.remove(this._onBlurObserver);
+            this.onKeyPressObservable.remove(this._onKeyPressObserver);
+
+            this._connectedInputText = null;
+        }
+
+        // Statics
+        public static CreateDefaultLayout(): VirtualKeyboard {
+            let returnValue = new VirtualKeyboard();
+
+            returnValue.addKeysRow(["1", "2", "3", "4", "5", "6", "7", "8", "9", "0","\u2190"]);
+            returnValue.addKeysRow(["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"]);
+            returnValue.addKeysRow(["a", "s", "d", "f", "g", "h", "j", "k", "l",";","'","\u21B5"]);
+            returnValue.addKeysRow(["z", "x", "c", "v", "b", "n", "m", ",", ".", "/"]);
+            returnValue.addKeysRow([" "], [{ width: "200px"}]);
+        
+            return returnValue;
+        }
+    }
+}

+ 4 - 3
localDev/index.html

@@ -3,8 +3,9 @@
 <head>
 	<title>Local Development</title>
 	
-    <script src="https://babylonjs.azurewebsites.net/cannon.js"></script>
-    <script src="https://babylonjs.azurewebsites.net/Oimo.js"></script>
+    <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
+	<script src="https://preview.babylonjs.com/cannon.js"></script>
+	<script src="https://preview.babylonjs.com/Oimo.js"></script>
 	<script src="../assets/refs/dat.gui.min.js"></script>
 	<script src="../tools/DevLoader/BabylonLoader.js"></script>
 	<script src="src/webgl-debug.js"></script>
@@ -39,7 +40,7 @@
 </head>
 <body>
 	<div id="fps">0</div>
-	<canvas id="renderCanvas"></canvas>
+	<canvas id="renderCanvas" touch-action="none"></canvas>
 	
 	<script>
 		var canvas = document.getElementById("renderCanvas");

+ 1 - 0
materialsLibrary/src/cell/babylon.cellMaterial.ts

@@ -18,6 +18,7 @@ module BABYLON {
         public NDOTL = true;
         public CUSTOMUSERLIGHTING = true;
         public CELLBASIC = true;
+        public DEPTHPREPASS = false;
         public USERIGHTHANDEDSYSTEM = false;
 
         constructor() {

+ 2 - 0
materialsLibrary/src/cell/cell.fragment.fx

@@ -107,6 +107,8 @@ void main(void)
 		discard;
 #endif
 
+#include<depthPrePass>
+
 	baseColor.rgb *= vDiffuseInfos.y;
 #endif
 

+ 1 - 0
materialsLibrary/src/fire/babylon.fireMaterial.ts

@@ -6,6 +6,7 @@ module BABYLON {
         public DIFFUSE = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public UV1 = false;

+ 2 - 0
materialsLibrary/src/fire/fire.fragment.fx

@@ -71,6 +71,8 @@ void main(void) {
 	if (opacityColor.r < 0.1)
 		discard;
 #endif
+
+#include<depthPrePass>
 	
 	baseColor = texture2D(diffuseSampler, perturbedBaseCoords.xy) * 2.0;
 	baseColor *= opacityColor;

+ 1 - 0
materialsLibrary/src/fur/babylon.furMaterial.ts

@@ -6,6 +6,7 @@ module BABYLON {
         public HEIGHTMAP = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public NORMAL = false;

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

@@ -70,6 +70,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 	baseColor.rgb *= vDiffuseInfos.y;
 #endif
 

+ 1 - 0
materialsLibrary/src/gradient/babylon.gradientMaterial.ts

@@ -5,6 +5,7 @@ module BABYLON {
         public DIFFUSE = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public LIGHT0 = false;

+ 2 - 0
materialsLibrary/src/gradient/gradient.fragment.fx

@@ -68,6 +68,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 #ifdef VERTEXCOLOR
 	baseColor.rgb *= vColor.rgb;
 #endif

+ 1 - 0
materialsLibrary/src/lava/babylon.lavaMaterial.ts

@@ -5,6 +5,7 @@ module BABYLON {
         public DIFFUSE = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public LIGHT0 = false;

+ 2 - 0
materialsLibrary/src/lava/lava.fragment.fx

@@ -108,6 +108,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 	baseColor.rgb *= vDiffuseInfos.y;
 #endif
 

+ 1 - 0
materialsLibrary/src/normal/babylon.normalMaterial.ts

@@ -5,6 +5,7 @@ module BABYLON {
         public DIFFUSE = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public LIGHT0 = false;

+ 2 - 0
materialsLibrary/src/normal/normal.fragment.fx

@@ -60,6 +60,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 	baseColor.rgb *= vDiffuseInfos.y;
 #endif
 

+ 1 - 0
materialsLibrary/src/simple/babylon.simpleMaterial.ts

@@ -5,6 +5,7 @@ module BABYLON {
         public DIFFUSE = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public NORMAL = false;

+ 2 - 0
materialsLibrary/src/simple/simple.fragment.fx

@@ -56,6 +56,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 	baseColor.rgb *= vDiffuseInfos.y;
 #endif
 

+ 1 - 0
materialsLibrary/src/terrain/babylon.terrainMaterial.ts

@@ -7,6 +7,7 @@ module BABYLON {
         public BUMP = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public SPECULARTERM = false;

+ 2 - 0
materialsLibrary/src/terrain/terrain.fragment.fx

@@ -137,6 +137,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 	baseColor.rgb *= vTextureInfos.y;
 	
 	vec4 diffuse1Color = texture2D(diffuse1Sampler, vTextureUV * diffuse1Infos);

+ 1 - 0
materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts

@@ -12,6 +12,7 @@ module BABYLON {
         
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public SPECULARTERM = false;

+ 2 - 0
materialsLibrary/src/triPlanar/triplanar.fragment.fx

@@ -108,6 +108,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 #ifdef VERTEXCOLOR
 	baseColor.rgb *= vColor.rgb;
 #endif

+ 1 - 0
materialsLibrary/src/water/babylon.waterMaterial.ts

@@ -6,6 +6,7 @@ module BABYLON {
         public REFLECTION = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public POINTSIZE = false;
         public FOG = false;
         public NORMAL = false;

+ 7 - 5
src/Behaviors/Cameras/babylon.framingBehavior.ts

@@ -205,12 +205,13 @@ module BABYLON {
 		 * @param radius Optional. If a cached radius position already exists, overrides default.
 		 * @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
 		 * @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
+		 * @param onAnimationEnd Callback triggered at the end of the framing animation
 		 */
-		public zoomOnMesh(mesh: AbstractMesh, focusOnOriginXZ: boolean = false): void {
+		public zoomOnMesh(mesh: AbstractMesh, focusOnOriginXZ: boolean = false, onAnimationEnd: () => void = null): void {
 			mesh.computeWorldMatrix(true);
 
 			let boundingBox = mesh.getBoundingInfo().boundingBox;
-			this.zoomOnBoundingInfo(boundingBox.minimumWorld, boundingBox.maximumWorld, focusOnOriginXZ);
+			this.zoomOnBoundingInfo(boundingBox.minimumWorld, boundingBox.maximumWorld, focusOnOriginXZ, onAnimationEnd);
 		}
 
 		/**
@@ -219,8 +220,9 @@ module BABYLON {
 		 * @param radius Optional. If a cached radius position already exists, overrides default.
 		 * @param framingPositionY Position on mesh to center camera focus where 0 corresponds bottom of its bounding box and 1, the top
 		 * @param focusOnOriginXZ Determines if the camera should focus on 0 in the X and Z axis instead of the mesh
+		 * @param onAnimationEnd Callback triggered at the end of the framing animation
 		 */
-		public zoomOnBoundingInfo(minimumWorld: Vector3, maximumWorld: Vector3, focusOnOriginXZ: boolean = false): void {
+		public zoomOnBoundingInfo(minimumWorld: Vector3, maximumWorld: Vector3, focusOnOriginXZ: boolean = false, onAnimationEnd: () => void = null): void {
 			let zoomTarget: BABYLON.Vector3;
 
 			// Find target by interpolating from bottom of bounding box in world-space to top via framingPositionY
@@ -265,8 +267,8 @@ module BABYLON {
 			}
 
 			this._animatables.push(Animation.TransitionTo("radius", radius, this._attachedCamera, this._attachedCamera.getScene(), 
-									60, this._radiusTransition, this._framingTime));															
-		}	
+				60, this._radiusTransition, this._framingTime, onAnimationEnd));
+		}
 		
 		/**
 		 * Calculates the lowest radius for the camera based on the bounding box of the mesh.

+ 39 - 8
src/Cameras/Inputs/babylon.arcRotateCameraPointersInput.ts

@@ -19,6 +19,9 @@ module BABYLON {
         @serialize()
         public panningSensibility: number = 50.0;
 
+        @serialize()
+        public multiTouchPanning: boolean = true;
+
         private _isPanClick: boolean = false;
         public pinchInwards = true;
 
@@ -35,7 +38,9 @@ module BABYLON {
             var engine = this.camera.getEngine();
             var cacheSoloPointer: { x: number, y: number, pointerId: number, type: any }; // cache pointer object for better perf on camera rotation
             var pointA: { x: number, y: number, pointerId: number, type: any }, pointB: { x: number, y: number, pointerId: number, type: any };
+            var previousPinchSquaredDistance = 0;
             var previousPinchDistance = 0;
+            var previousMultiTouchPanPosition: { x: number, y: number, isPaning: boolean } = { x: 0, y:0, isPaning: false };
 
             this._pointerInput = (p, s) => {
                 var evt = <PointerEvent>p.event;
@@ -78,7 +83,9 @@ module BABYLON {
                     }
 
                     cacheSoloPointer = null;
+                    previousPinchSquaredDistance = 0;
                     previousPinchDistance = 0;
+                    previousMultiTouchPanPosition.isPaning = false;
 
                     //would be better to use pointers.remove(evt.pointerId) for multitouch gestures, 
                     //but emptying completly pointers collection is required to fix a bug on iPhone : 
@@ -97,8 +104,7 @@ module BABYLON {
                     // One button down
                     if (pointA && pointB === undefined) {
                         if (this.panningSensibility !== 0 &&
-                            ((evt.ctrlKey && this.camera._useCtrlForPanning) ||
-                                (!this.camera._useCtrlForPanning && this._isPanClick))) {
+                            ((evt.ctrlKey && this.camera._useCtrlForPanning) || this._isPanClick)) {
                             this.camera.inertialPanningX += -(evt.clientX - cacheSoloPointer.x) / this.panningSensibility;
                             this.camera.inertialPanningY += (evt.clientY - cacheSoloPointer.y) / this.panningSensibility;
                         } else {
@@ -112,7 +118,7 @@ module BABYLON {
                         cacheSoloPointer.y = evt.clientY;
                     }
 
-                    // Two buttons down: pinch
+                    // Two buttons down: pinch/pan
                     else if (pointA && pointB) {
                         //if (noPreventDefault) { evt.preventDefault(); } //if pinch gesture, could be useful to force preventDefault to avoid html page scroll/zoom in some mobile browsers
                         var ed = (pointA.pointerId === evt.pointerId) ? pointA : pointB;
@@ -122,19 +128,42 @@ module BABYLON {
                         var distX = pointA.x - pointB.x;
                         var distY = pointA.y - pointB.y;
                         var pinchSquaredDistance = (distX * distX) + (distY * distY);
-                        if (previousPinchDistance === 0) {
-                            previousPinchDistance = pinchSquaredDistance;
+                        var pinchDistance = Math.sqrt(pinchSquaredDistance);
+                        if (previousPinchSquaredDistance === 0) {
+                            previousPinchSquaredDistance = pinchSquaredDistance;
+                            previousPinchDistance = pinchDistance;
                             return;
                         }
 
-                        if (pinchSquaredDistance !== previousPinchDistance) {
+                        if (Math.abs(pinchDistance - previousPinchDistance) > this.camera.pinchToPanMaxDistance) {
                             this.camera
-                                .inertialRadiusOffset += (pinchSquaredDistance - previousPinchDistance) /
+                                .inertialRadiusOffset += (pinchSquaredDistance - previousPinchSquaredDistance) /
                                 (this.pinchPrecision *
                                     ((this.angularSensibilityX + this.angularSensibilityY) / 2) *
                                     direction);
-                            previousPinchDistance = pinchSquaredDistance;
+                            previousMultiTouchPanPosition.isPaning = false;
+                        }
+                        else {
+                            if (cacheSoloPointer.pointerId === ed.pointerId && this.panningSensibility !== 0 && this.multiTouchPanning) {
+                                if (!previousMultiTouchPanPosition.isPaning) {
+                                    previousMultiTouchPanPosition.isPaning = true;
+                                    previousMultiTouchPanPosition.x = ed.x;
+                                    previousMultiTouchPanPosition.y = ed.y;
+                                    return;
+                                }
+
+                                this.camera.inertialPanningX += -(ed.x - previousMultiTouchPanPosition.x) / this.panningSensibility;
+                                this.camera.inertialPanningY += (ed.y - previousMultiTouchPanPosition.y) / this.panningSensibility;
+                            }
                         }
+
+                        if (cacheSoloPointer.pointerId === evt.pointerId) {
+                            previousMultiTouchPanPosition.x = ed.x;
+                            previousMultiTouchPanPosition.y = ed.y;
+                        }
+
+                        previousPinchSquaredDistance = pinchSquaredDistance;
+                        previousPinchDistance = pinchDistance;
                     }
                 }
             }
@@ -152,7 +181,9 @@ module BABYLON {
             this._onLostFocus = () => {
                 //this._keys = [];
                 pointA = pointB = undefined;
+                previousPinchSquaredDistance = 0;
                 previousPinchDistance = 0;
+                previousMultiTouchPanPosition.isPaning = false;
                 cacheSoloPointer = null;
             };
 

+ 22 - 4
src/Cameras/babylon.arcRotateCamera.ts

@@ -57,6 +57,15 @@ module BABYLON {
         public inertialPanningY: number = 0;
 
         @serialize()
+        public pinchToPanMaxDistance: number = 2;
+
+        @serialize()
+        public panningDistanceLimit: number = null;
+
+        @serializeAsVector3()
+        public panningOriginTarget: Vector3 = Vector3.Zero();
+
+        @serialize()
         public panningInertia = 0.9;
 
         //-- begin properties for backward compatibility for inputs
@@ -365,8 +374,8 @@ module BABYLON {
         /**
          * Restored camera state. You must call storeState() first
          */
-        public restoreState(): boolean {
-            if (!super.restoreState()) {
+        public _restoreStateValues(): boolean {
+            if (!super._restoreStateValues()) {
                 return false;
             }
 
@@ -382,7 +391,7 @@ module BABYLON {
             this.inertialPanningY = 0;
         
             return true;
-        }             
+        }
 
         // Synchronized
         public _isSynchronizedViewMatrix(): boolean {
@@ -467,7 +476,16 @@ module BABYLON {
                 }
 
                 if (!this._targetHost) {
-                    this._target.addInPlace(this._transformedDirection);
+                    if (this.panningDistanceLimit) {
+                        this._transformedDirection.addInPlace(this._target);
+                        var distanceSquared = Vector3.DistanceSquared(this._transformedDirection, this.panningOriginTarget);
+                        if (distanceSquared <= (this.panningDistanceLimit * this.panningDistanceLimit)) {
+                            this._target.copyFrom(this._transformedDirection);
+                        }
+                    }
+                    else {
+                        this._target.addInPlace(this._transformedDirection);
+                    }
                 }
 
                 this.inertialPanningX *= this.panningInertia;

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

@@ -127,6 +127,7 @@
         public onViewMatrixChangedObservable = new Observable<Camera>();
         public onProjectionMatrixChangedObservable = new Observable<Camera>();
         public onAfterCheckInputsObservable = new Observable<Camera>();
+        public onRestoreStateObservable = new Observable<Camera>();
 
         // Cache
         private _computedViewMatrix = Matrix.Identity();
@@ -168,9 +169,9 @@
         }
 
         /**
-         * Restored camera state. You must call storeState() first
+         * Restores the camera state values if it has been stored. You must call storeState() first
          */
-        public restoreState(): boolean {
+        protected _restoreStateValues(): boolean {
             if (!this._stateStored) {
                 return false;
             }
@@ -180,6 +181,18 @@
             return true;
         }
 
+        /**
+         * Restored camera state. You must call storeState() first
+         */
+        public restoreState(): boolean {
+            if (this._restoreStateValues()) {
+                this.onRestoreStateObservable.notifyObservers(this);
+                return true;
+            }
+
+            return false;
+        }
+
         public getClassName(): string {
             return "Camera";
         }
@@ -577,6 +590,7 @@
             this.onViewMatrixChangedObservable.clear();
             this.onProjectionMatrixChangedObservable.clear();
             this.onAfterCheckInputsObservable.clear();
+            this.onRestoreStateObservable.clear();
 
             // Inputs
             if (this.inputs) {

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

@@ -79,8 +79,8 @@ module BABYLON {
         /**
          * Restored camera state. You must call storeState() first
          */
-        public restoreState(): boolean {
-            if (!super.restoreState()) {
+        public _restoreStateValues(): boolean {
+            if (!super._restoreStateValues()) {
                 return false;
             }
 

+ 11 - 1
src/Layer/babylon.highlightlayer.ts

@@ -486,11 +486,21 @@ module BABYLON {
                 }
             };
 
-            this._mainTexture.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>): void => {
+            this._mainTexture.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void => {
                 this.onBeforeRenderMainTextureObservable.notifyObservers(this);
 
                 var index: number;
 
+                let engine = this._scene.getEngine();
+                
+                if (depthOnlySubMeshes.length) {
+                    engine.setColorWrite(false);            
+                    for (index = 0; index < depthOnlySubMeshes.length; index++) {
+                        renderSubMesh(depthOnlySubMeshes.data[index]);
+                    }
+                    engine.setColorWrite(true);
+                }                
+
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
                     renderSubMesh(opaqueSubMeshes.data[index]);
                 }

+ 11 - 1
src/Lights/Shadows/babylon.shadowGenerator.ts

@@ -444,8 +444,18 @@
             }
         }
 
-        private _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>): void {
+        private _renderForShadowMap(opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void {
             var index: number;
+            let engine = this._scene.getEngine();
+
+            if (depthOnlySubMeshes.length) {
+                engine.setColorWrite(false);            
+                for (index = 0; index < depthOnlySubMeshes.length; index++) {
+                    this._renderSubMeshForShadowMap(depthOnlySubMeshes.data[index]);
+                }
+                engine.setColorWrite(true);
+            }
+            
             for (index = 0; index < opaqueSubMeshes.length; index++) {
                 this._renderSubMeshForShadowMap(opaqueSubMeshes.data[index]);
             }

+ 1 - 0
src/Materials/PBR/babylon.pbrBaseMaterial.ts

@@ -20,6 +20,7 @@
         public OPACITYDIRECTUV = 0;
         public OPACITYRGB = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public ALPHABLEND = false;
         public ALPHAFROMALBEDO = false;
         public ALPHATESTVALUE = 0.5;

+ 2 - 0
src/Materials/Textures/babylon.mirrorTexture.ts

@@ -61,6 +61,8 @@ module BABYLON {
         constructor(name: string, size: any, scene: Scene, generateMipMaps?: boolean, type: number = Engine.TEXTURETYPE_UNSIGNED_INT, samplingMode = Texture.BILINEAR_SAMPLINGMODE, generateDepthBuffer = true) {
             super(name, size, scene, generateMipMaps, true, type, false, samplingMode, generateDepthBuffer);
 
+            this.ignoreCameraViewport = true;
+
             this.onBeforeRenderObservable.add(() => {
                 Matrix.ReflectionToRef(this.mirrorPlane, this._mirrorMatrix);
                 this._savedViewMatrix = scene.getViewMatrix();

+ 16 - 0
src/Materials/Textures/babylon.multiRenderTarget.ts

@@ -29,6 +29,22 @@ module BABYLON {
             return this._textures[this._textures.length - 1];
         }
 
+        public set wrapU (wrap: number) {
+            if (this._textures) {
+                for (var i = 0; i < this._textures.length; i++) {
+                    this._textures[i].wrapU = wrap;
+                }
+            }
+        }
+
+        public set wrapV (wrap: number) {
+            if (this._textures) {
+                for (var i = 0; i < this._textures.length; i++) {
+                    this._textures[i].wrapV = wrap;
+                }
+            }
+        }
+
         constructor(name: string, size: any, count: number, scene: Scene, options?: any) {
             options = options || {};
 

+ 1 - 1
src/Materials/Textures/babylon.renderTargetTexture.ts

@@ -30,7 +30,7 @@
         public renderSprites = false;
         public coordinatesMode = Texture.PROJECTION_MODE;
         public activeCamera: Camera;
-        public customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, beforeTransparents?: () => void) => void;
+        public customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>, beforeTransparents?: () => void) => void;
         public useCameraPostProcesses: boolean;
         public ignoreCameraViewport: boolean = false;
 

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

@@ -378,12 +378,15 @@
                 callback(preparedSourceCode.replace("#version 300 es", ""));
                 return;
             }
+
+            var hasDrawBuffersExtension = preparedSourceCode.search(/#extension.+GL_EXT_draw_buffers.+require/) !== -1;
             
             // Remove extensions 
             // #extension GL_OES_standard_derivatives : enable
             // #extension GL_EXT_shader_texture_lod : enable
             // #extension GL_EXT_frag_depth : enable
-            var regex = /#extension.+(GL_OES_standard_derivatives|GL_EXT_shader_texture_lod|GL_EXT_frag_depth).+enable/g;
+            // #extension GL_EXT_draw_buffers : require
+            var regex = /#extension.+(GL_OES_standard_derivatives|GL_EXT_shader_texture_lod|GL_EXT_frag_depth|GL_EXT_draw_buffers).+(enable|require)/g;
             var result = preparedSourceCode.replace(regex, "");
 
             // Migrate to GLSL v300
@@ -398,7 +401,8 @@
                 result = result.replace(/textureCube\(/g, "texture(");
                 result = result.replace(/gl_FragDepthEXT/g, "gl_FragDepth");
                 result = result.replace(/gl_FragColor/g, "glFragColor");
-                result = result.replace(/void\s+?main\(/g, "out vec4 glFragColor;\nvoid main(");
+                result = result.replace(/gl_FragData/g, "glFragData");
+                result = result.replace(/void\s+?main\(/g, (hasDrawBuffersExtension ? "" : "out vec4 glFragColor;\n") + "void main(");
             }
             
             callback(result);

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

@@ -285,6 +285,9 @@
         public alphaMode = Engine.ALPHA_COMBINE;
 
         @serialize()
+        public needDepthPrePass = false;
+
+        @serialize()
         public disableDepthWrite = false;
 
         @serialize("fogEnabled")

+ 5 - 0
src/Materials/babylon.materialHelper.ts

@@ -46,6 +46,11 @@
                 changed = true;
             }
 
+            if (defines["DEPTHPREPASS"] !== !engine.getColorWrite()) {
+                defines["DEPTHPREPASS"] = !defines["DEPTHPREPASS"];
+                changed = true;
+            }            
+
             if (defines["INSTANCES"] !== useInstances) {
                 defines["INSTANCES"] = useInstances;
                 changed = true;

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

@@ -21,6 +21,7 @@ module BABYLON {
         public SPECULAROVERALPHA = false;
         public CLIPPLANE = false;
         public ALPHATEST = false;
+        public DEPTHPREPASS = false;
         public ALPHAFROMDIFFUSE = false;
         public POINTSIZE = false;
         public FOG = false;

+ 3 - 1
src/PostProcess/RenderPipeline/Pipelines/babylon.defaultRenderingPipeline.ts

@@ -223,8 +223,10 @@
                 this.imageProcessing = new BABYLON.ImageProcessingPostProcess("imageProcessing",  1.0, null, BABYLON.Texture.BILINEAR_SAMPLINGMODE, engine, false, this._defaultPipelineTextureType);
                 if (this._hdr) {
                     this.addEffect(new PostProcessRenderEffect(engine, this.ImageProcessingPostProcessId, () => { return this.imageProcessing; }, true));
+                } else {
+                    this._scene.imageProcessingConfiguration.applyByPostProcess = false;
                 }
-            }
+            } 
 
 			if (this.fxaaEnabled) {
                 this.fxaa = new FxaaPostProcess("fxaa", 1.0, null, Texture.BILINEAR_SAMPLINGMODE, engine, false, this._defaultPipelineTextureType);

+ 1 - 1
src/PostProcess/RenderPipeline/Pipelines/babylon.ssao2RenderingPipeline.ts

@@ -120,7 +120,7 @@
         */
         public static get IsSupported(): boolean {
             var engine = Engine.LastCreatedEngine;
-            return engine.webGLVersion > 1;
+            return engine.getCaps().drawBuffersExtension;
         }
 
         private _scene: Scene;

+ 2 - 3
src/PostProcess/RenderPipeline/Pipelines/babylon.standardRenderingPipeline.ts

@@ -726,9 +726,8 @@
         }
 
         private _getDepthTexture(): Texture {
-            var geometry = this._scene.enableGeometryBufferRenderer();
-            if (geometry) {
-                return geometry.getGBuffer().textures[0];
+            if (this._scene.getEngine().getCaps().drawBuffersExtension) {
+                return this._scene.enableGeometryBufferRenderer().getGBuffer().textures[0];
             }
 
             return this._scene.enableDepthRenderer().getDepthMap();

+ 11 - 1
src/PostProcess/babylon.postProcess.ts

@@ -20,6 +20,7 @@
         public scaleMode = Engine.SCALEMODE_FLOOR;
         public alwaysForcePOT = false;
         public samples = 1;
+        public adaptScaleToCurrentViewport = false;
 
         private _camera: Camera;
         private _scene: Scene;
@@ -221,9 +222,18 @@
                 var requiredWidth = ((sourceTexture ? sourceTexture.width : this._engine.getRenderingCanvas().width) * <number>this._options) | 0;
                 var requiredHeight = ((sourceTexture ? sourceTexture.height : this._engine.getRenderingCanvas().height) * <number>this._options) | 0;
 
-                var desiredWidth = (<PostProcessOptions>this._options).width || requiredWidth;
+                var desiredWidth = ((<PostProcessOptions>this._options).width || requiredWidth);
                 var desiredHeight = (<PostProcessOptions>this._options).height || requiredHeight;
 
+                if (this.adaptScaleToCurrentViewport) {
+                    let currentViewport = engine.currentViewport;
+
+                    if (currentViewport) {
+                        desiredWidth *= currentViewport.width;
+                        desiredHeight *= currentViewport.height;
+                    }
+                }
+
                 if (this.renderTargetSamplingMode === Texture.TRILINEAR_SAMPLINGMODE || this.alwaysForcePOT) {
                     if (!(<PostProcessOptions>this._options).width) {
                         desiredWidth = engine.needPOTTextures ? Tools.GetExponentOfTwo(desiredWidth, maxSize, this.scaleMode) : desiredWidth;

+ 9 - 1
src/PostProcess/babylon.volumetricLightScatteringPostProcess.ts

@@ -333,9 +333,17 @@
                 scene.clearColor = savedSceneClearColor;
             });
             
-            this._volumetricLightScatteringRTT.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>): void => {
+            this._volumetricLightScatteringRTT.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void => {
                 var engine = scene.getEngine();
                 var index: number;
+                
+                if (depthOnlySubMeshes.length) {
+                    engine.setColorWrite(false);            
+                    for (index = 0; index < depthOnlySubMeshes.length; index++) {
+                        renderSubMesh(depthOnlySubMeshes.data[index]);
+                    }
+                    engine.setColorWrite(true);
+                }                   
 
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
                     renderSubMesh(opaqueSubMeshes.data[index]);

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

@@ -10,7 +10,6 @@
         private _scaleFactor: Vector2;
         private _lensCenter: Vector2;
 
-        //ANY
         constructor(name: string, camera: Camera, isRightEye: boolean, vrMetrics: VRCameraMetrics) {
             super(name, "vrDistortionCorrection", [
                 'LensCenter',
@@ -23,6 +22,7 @@
             this._distortionFactors = vrMetrics.distortionK;
             this._postProcessScaleFactor = vrMetrics.postProcessScaleFactor;
             this._lensCenterOffset = vrMetrics.lensCenterOffset;
+            this.adaptScaleToCurrentViewport = true;
 
             this.onSizeChangedObservable.add(() => {
                 this.aspectRatio = this.width * .5 / this.height;

+ 9 - 1
src/Rendering/babylon.depthRenderer.ts

@@ -73,9 +73,17 @@
                 }
             };
 
-            this._depthMap.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>): void => {
+            this._depthMap.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void => {
                 var index;
 
+                if (depthOnlySubMeshes.length) {
+                    engine.setColorWrite(false);            
+                    for (index = 0; index < depthOnlySubMeshes.length; index++) {
+                        renderSubMesh(depthOnlySubMeshes.data[index]);
+                    }
+                    engine.setColorWrite(true);
+                }     
+
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
                     renderSubMesh(opaqueSubMeshes.data[index]);
                 }

+ 12 - 2
src/Rendering/babylon.geometryBufferRenderer.ts

@@ -102,7 +102,9 @@ module BABYLON {
                 this._effect = this._scene.getEngine().createEffect("geometry",
                     attribs,
                     ["world", "mBones", "viewProjection", "diffuseMatrix", "view"],
-                    ["diffuseSampler"], join);
+                    ["diffuseSampler"], join,
+                    null, null, null,
+                    { buffersCount: this._enablePosition ? 3 : 2 });
             }
 
             return this._effect.isReady();
@@ -180,9 +182,17 @@ module BABYLON {
                 }
             };
 
-            this._multiRenderTarget.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>): void => {
+            this._multiRenderTarget.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void => {
                 var index;
 
+                if (depthOnlySubMeshes.length) {
+                    engine.setColorWrite(false);            
+                    for (index = 0; index < depthOnlySubMeshes.length; index++) {
+                        renderSubMesh(depthOnlySubMeshes.data[index]);
+                    }
+                    engine.setColorWrite(true);
+                }                  
+
                 for (index = 0; index < opaqueSubMeshes.length; index++) {
                     renderSubMesh(opaqueSubMeshes.data[index]);
                 }

+ 25 - 11
src/Rendering/babylon.outlineRenderer.ts

@@ -24,6 +24,13 @@
             var material = subMesh.getMaterial();
 
             engine.enableEffect(this._effect);
+
+            // Logarithmic depth
+            if((<any> material).useLogarithmicDepth)
+            {
+                this._effect.setFloat("logarithmicDepthConstant", 2.0 / (Math.log(scene.activeCamera.maxZ + 1.0) / Math.LN2));
+            }
+
             this._effect.setFloat("offset", useOverlay ? 0 : mesh.outlineWidth);
             this._effect.setColor4("color", useOverlay ? mesh.overlayColor : mesh.outlineColor, useOverlay ? mesh.overlayAlpha : material.alpha);
             this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
@@ -59,19 +66,26 @@
             var mesh = subMesh.getMesh();
             var material = subMesh.getMaterial();
 
-            // Alpha test
-            if (material && material.needAlphaTesting()) {
-                defines.push("#define ALPHATEST");
-                if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
-                    attribs.push(VertexBuffer.UVKind);
-                    defines.push("#define UV1");
+            if (material) {
+                // Alpha test
+                if(material.needAlphaTesting())
+                {
+                    defines.push("#define ALPHATEST");
+                    if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
+                        attribs.push(VertexBuffer.UVKind);
+                        defines.push("#define UV1");
+                    }
+                    if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
+                        attribs.push(VertexBuffer.UV2Kind);
+                        defines.push("#define UV2");
+                    }
                 }
-                if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
-                    attribs.push(VertexBuffer.UV2Kind);
-                    defines.push("#define UV2");
+                //Logarithmic depth
+                if((<any> material).useLogarithmicDepth)
+                {
+                    defines.push("#define LOGARITHMICDEPTH");
                 }
             }
-
             // Bones
             if (mesh.useBones && mesh.computeBonesUsingShaders) {
                 attribs.push(VertexBuffer.MatricesIndicesKind);
@@ -101,7 +115,7 @@
                 this._cachedDefines = join;
                 this._effect = this._scene.getEngine().createEffect("outline",
                     attribs,
-                    ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color"],
+                    ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color", "logarithmicDepthConstant"],
                     ["diffuseSampler"], join);
             }
 

+ 39 - 3
src/Rendering/babylon.renderingGroup.ts

@@ -4,6 +4,7 @@
         private _opaqueSubMeshes = new SmartArray<SubMesh>(256);
         private _transparentSubMeshes = new SmartArray<SubMesh>(256);
         private _alphaTestSubMeshes = new SmartArray<SubMesh>(256);
+        private _depthOnlySubMeshes = new SmartArray<SubMesh>(256);
         private _particleSystems = new SmartArray<IParticleSystem>(256);
         private _spriteManagers = new SmartArray<SpriteManager>(256);        
         private _activeVertices: number;
@@ -85,13 +86,22 @@
          * @param customRenderFunction Used to override the default render behaviour of the group.
          * @returns true if rendered some submeshes.
          */
-        public render(customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>) => void, renderSprites: boolean, renderParticles: boolean, activeMeshes: AbstractMesh[]): void {
+        public render(customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>) => void, renderSprites: boolean, renderParticles: boolean, activeMeshes: AbstractMesh[]): void {
             if (customRenderFunction) {
-                customRenderFunction(this._opaqueSubMeshes, this._alphaTestSubMeshes, this._transparentSubMeshes);
+                customRenderFunction(this._opaqueSubMeshes, this._alphaTestSubMeshes, this._transparentSubMeshes, this._depthOnlySubMeshes);
                 return;
             }
 
             var engine = this._scene.getEngine();
+
+            // Depth only
+            if (this._depthOnlySubMeshes.length !== 0) {
+                engine.setAlphaTesting(true);
+                engine.setColorWrite(false);
+                this._renderAlphaTest(this._depthOnlySubMeshes);
+                engine.setAlphaTesting(false);
+                engine.setColorWrite(true);
+            }            
             
             // Opaque
             if (this._opaqueSubMeshes.length !== 0) {
@@ -107,6 +117,7 @@
 
             var stencilState = engine.getStencilBuffer();
             engine.setStencilBuffer(false);
+
             // Sprites
             if (renderSprites) {
                 this._renderSprites();
@@ -172,7 +183,7 @@
          */
         private static renderSorted(subMeshes: SmartArray<SubMesh>, sortCompareFn: (a: SubMesh, b: SubMesh) => number, cameraPosition: Vector3, transparent: boolean): void {
             let subIndex = 0;
-            let subMesh;
+            let subMesh: SubMesh;
             for (; subIndex < subMeshes.length; subIndex++) {
                 subMesh = subMeshes.data[subIndex];
                 subMesh._alphaIndex = subMesh.getMesh().alphaIndex;
@@ -184,6 +195,21 @@
 
             for (subIndex = 0; subIndex < sortedArray.length; subIndex++) {
                 subMesh = sortedArray[subIndex];
+
+                if (transparent) {
+                    let material = subMesh.getMaterial();
+
+                    if (material.needDepthPrePass) {
+                        let engine = material.getScene().getEngine();
+                        engine.setColorWrite(false);
+                        engine.setAlphaTesting(true);
+                        engine.setAlphaMode(Engine.ALPHA_DISABLE);
+                        subMesh.render(false);
+                        engine.setAlphaTesting(false);
+                        engine.setColorWrite(true);
+                    }
+                }
+
                 subMesh.render(transparent);
             }
         }
@@ -267,6 +293,7 @@
             this._opaqueSubMeshes.reset();
             this._transparentSubMeshes.reset();
             this._alphaTestSubMeshes.reset();
+            this._depthOnlySubMeshes.reset();
             this._particleSystems.reset();
             this._spriteManagers.reset();            
             this._edgesRenderers.reset();
@@ -276,6 +303,7 @@
             this._opaqueSubMeshes.dispose();
             this._transparentSubMeshes.dispose();
             this._alphaTestSubMeshes.dispose();
+            this._depthOnlySubMeshes.dispose();
             this._particleSystems.dispose();
             this._spriteManagers.dispose();                      
             this._edgesRenderers.dispose();
@@ -292,8 +320,16 @@
             if (material.needAlphaBlending() || mesh.visibility < 1.0 || mesh.hasVertexAlpha) { // Transparent
                 this._transparentSubMeshes.push(subMesh);
             } else if (material.needAlphaTesting()) { // Alpha test
+                if (material.needDepthPrePass) {
+                    this._depthOnlySubMeshes.push(subMesh);
+                }
+                
                 this._alphaTestSubMeshes.push(subMesh);
             } else {
+                if (material.needDepthPrePass) {
+                    this._depthOnlySubMeshes.push(subMesh);
+                }
+                
                 this._opaqueSubMeshes.push(subMesh); // Opaque
             }
 

+ 1 - 1
src/Rendering/babylon.renderingManager.ts

@@ -55,7 +55,7 @@
             this._depthStencilBufferAlreadyCleaned = true;
         }
 
-        public render(customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>) => void,
+        public render(customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>) => void,
             activeMeshes: AbstractMesh[], renderParticles: boolean, renderSprites: boolean): void {          
                   
             // Check if there's at least on observer on the onRenderingGroupObservable and initialize things to fire it

+ 4 - 0
src/Shaders/ShadersInclude/depthPrePass.fx

@@ -0,0 +1,4 @@
+#ifdef DEPTHPREPASS
+	gl_FragColor = vec4(0., 0., 0., 1.0);
+	return;
+#endif

+ 3 - 0
src/Shaders/ShadersInclude/mrtFragmentDeclaration.fx

@@ -0,0 +1,3 @@
+#if __VERSION__ >= 200
+layout(location = 0) out vec4 glFragData[{X}];
+#endif

+ 2 - 0
src/Shaders/default.fragment.fx

@@ -185,6 +185,8 @@ void main(void) {
 		discard;
 #endif
 
+#include<depthPrePass>
+
 #ifdef ALPHAFROMDIFFUSE
 	alpha *= baseColor.a;
 #endif

+ 13 - 13
src/Shaders/geometry.fragment.fx

@@ -1,38 +1,38 @@
-#version 300 es
+#extension GL_EXT_draw_buffers : require
 
 precision highp float;
 precision highp int;
 
-in vec3 vNormalV;
-in vec4 vViewPos;
+varying vec3 vNormalV;
+varying vec4 vViewPos;
 
 #ifdef POSITION
-in vec3 vPosition;
+varying vec3 vPosition;
 #endif
 
 #ifdef ALPHATEST
-in vec2 vUV;
+varying vec2 vUV;
 uniform sampler2D diffuseSampler;
 #endif
 
-layout(location = 0) out vec4 color0;
-layout(location = 1) out vec4 color1;
-
 #ifdef POSITION
-layout(location = 2) out vec4 color2;
+#include<mrtFragmentDeclaration>[3]
+#else
+#include<mrtFragmentDeclaration>[2]
 #endif
 
 void main() {
 #ifdef ALPHATEST
-	if (texture(diffuseSampler, vUV).a < 0.4)
+	if (texture2D(diffuseSampler, vUV).a < 0.4)
 		discard;
 #endif
 
-    color0 = vec4(vViewPos.z / vViewPos.w, 0.0, 0.0, 1.0);
-    color1 = vec4(normalize(vNormalV), 1.0);
+    gl_FragData[0] = vec4(vViewPos.z / vViewPos.w, 0.0, 0.0, 1.0);
+    //color0 = vec4(vViewPos.z / vViewPos.w, 0.0, 0.0, 1.0);
+    gl_FragData[1] = vec4(normalize(vNormalV), 1.0);
     //color2 = vec4(vPositionV, 1.0);
 
     #ifdef POSITION
-    color2 = vec4(vPosition, 1.0);
+    gl_FragData[2] = vec4(vPosition, 1.0);
     #endif
 }

+ 10 - 12
src/Shaders/geometry.vertex.fx

@@ -1,22 +1,20 @@
-#version 300 es
-
 precision highp float;
 precision highp int;
 
-#include<bones300Declaration>
-#include<instances300Declaration>
+#include<bonesDeclaration>
+#include<instancesDeclaration>
 
-in vec3 position;
-in vec3 normal;
+attribute vec3 position;
+attribute vec3 normal;
 
 #if defined(ALPHATEST) || defined(NEED_UV)
-out vec2 vUV;
+varying vec2 vUV;
 uniform mat4 diffuseMatrix;
 #ifdef UV1
-in vec2 uv;
+varying vec2 uv;
 #endif
 #ifdef UV2
-in vec2 uv2;
+varying vec2 uv2;
 #endif
 #endif
 
@@ -24,11 +22,11 @@ in vec2 uv2;
 uniform mat4 viewProjection;
 uniform mat4 view;
 
-out vec3 vNormalV;
-out vec4 vViewPos;
+varying vec3 vNormalV;
+varying vec4 vViewPos;
 
 #ifdef POSITION
-out vec3 vPosition;
+varying vec3 vPosition;
 #endif
 
 void main(void)

+ 6 - 2
src/Shaders/outline.fragment.fx

@@ -1,15 +1,19 @@
-uniform vec4 color;
+#ifdef LOGARITHMICDEPTH
+#extension GL_EXT_frag_depth : enable
+#endif
+uniform vec4 color;
 
 #ifdef ALPHATEST
 varying vec2 vUV;
 uniform sampler2D diffuseSampler;
 #endif
+#include<logDepthDeclaration>
 
 void main(void) {
 #ifdef ALPHATEST
 	if (texture2D(diffuseSampler, vUV).a < 0.4)
 		discard;
 #endif
-
+#include<logDepthFragment>
 	gl_FragColor = color;
 }

+ 2 - 0
src/Shaders/outline.vertex.fx

@@ -21,6 +21,7 @@ attribute vec2 uv;
 attribute vec2 uv2;
 #endif
 #endif
+#include<logDepthDeclaration>
 
 void main(void)
 {
@@ -39,4 +40,5 @@ void main(void)
 	vUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));
 #endif
 #endif
+#include<logDepthVertex>
 }

+ 2 - 0
src/Shaders/pbr.fragment.fx

@@ -288,6 +288,8 @@ void main(void) {
 	#endif
 #endif
 
+#include<depthPrePass>
+
 #ifdef VERTEXCOLOR
 	surfaceAlbedo *= vColor.rgb;
 #endif

+ 2 - 2
src/Shaders/ssao2.fragment.fx

@@ -40,7 +40,7 @@ uniform mat4 projection;
 void main()
 {
 	vec3 random = texture2D(randomSampler, vUV * randTextureTiles).rgb;
-	float depth = abs(texture(textureSampler, vUV).r);
+	float depth = abs(texture2D(textureSampler, vUV).r);
 	vec3 normal = texture2D(normalSampler, vUV).rgb; 
 	float occlusion = 0.0;
 	float correctedRadius = min(radius, minZAspect * depth / near);
@@ -76,7 +76,7 @@ void main()
 	   }
 	  
 		// get sample linearDepth:
-	   float sampleDepth = abs(texture(textureSampler, offset.xy).r);
+	   float sampleDepth = abs(texture2D(textureSampler, offset.xy).r);
 		// range check & accumulate:
 	   float rangeCheck = abs(depth - sampleDepth) < correctedRadius ? 1.0 : 0.0;
 	   difference = samplePosition.z - sampleDepth;

+ 17 - 15
src/Tools/babylon.tools.ts

@@ -315,22 +315,24 @@
          * @param func - the function to be called
          * @param requester - the object that will request the next frame. Falls back to window.
          */
-        public static QueueNewFrame(func, requester: any = window): void {
-            //if WebVR is enabled AND presenting, requestAnimationFrame is triggered when enabled.
-            /*if(requester.isPresenting) {
-                return;
-            } else*/ if (requester.requestAnimationFrame)
-                requester.requestAnimationFrame(func);
-            else if (requester.msRequestAnimationFrame)
-                requester.msRequestAnimationFrame(func);
-            else if (requester.webkitRequestAnimationFrame)
-                requester.webkitRequestAnimationFrame(func);
-            else if (requester.mozRequestAnimationFrame)
-                requester.mozRequestAnimationFrame(func);
-            else if (requester.oRequestAnimationFrame)
-                requester.oRequestAnimationFrame(func);
+        public static QueueNewFrame(func, requester: any = window): number {
+            if (requester.requestAnimationFrame) {
+                return requester.requestAnimationFrame(func);
+            }
+            else if (requester.msRequestAnimationFrame) {
+                return requester.msRequestAnimationFrame(func);
+            }
+            else if (requester.webkitRequestAnimationFrame) {
+                return requester.webkitRequestAnimationFrame(func);
+            }
+            else if (requester.mozRequestAnimationFrame) {
+                return requester.mozRequestAnimationFrame(func);
+            }
+            else if (requester.oRequestAnimationFrame) {
+                return requester.oRequestAnimationFrame(func);
+            }
             else {
-                window.setTimeout(func, 16);
+                return window.setTimeout(func, 16);
             }
         }
 

+ 88 - 44
src/babylon.engine.ts

@@ -239,7 +239,8 @@
         public textureHalfFloatLinearFiltering: boolean;
         public textureHalfFloatRender: boolean;
         public textureLOD: boolean;
-        public drawBuffersExtension;
+        public drawBuffersExtension: boolean;
+        public depthTextureExtension: boolean;
         public colorBufferFloat: boolean;
     }
 
@@ -563,7 +564,6 @@
         private _vrDisplayEnabled;
         private _oldSize: BABYLON.Size;
         private _oldHardwareScaleFactor: number;
-        private _vrAnimationFrameHandler: number;
 
         // Uniform buffers list
         public disableUniformBuffers = false;
@@ -613,6 +613,7 @@
         private _pointerLockRequested: boolean;
         private _alphaTest: boolean;
         private _isStencilEnable: boolean;
+        private _colorWrite = true;
 
         private _loadingScreen: ILoadingScreen;
 
@@ -696,6 +697,8 @@
         private _emptyTexture: InternalTexture;
         private _emptyCubeTexture: InternalTexture;
 
+        private _frameHandler: number;
+
         // Hardware supported Compressed Textures
         private _texturesSupported = new Array<string>();
         private _textureFormatInUse: string;
@@ -708,6 +711,10 @@
             return this._textureFormatInUse;
         }
 
+        public get currentViewport(): Viewport {
+            return this._cachedViewport;
+        }
+
         // Empty texture
         public get emptyTexture(): InternalTexture {
             if (!this._emptyTexture) {
@@ -829,52 +836,55 @@
                 window.addEventListener("focus", this._onFocus);
 
                 canvas.addEventListener("pointerout", this._onCanvasPointerOut);
-            } else {
-                this._gl = <WebGLRenderingContext>canvasOrContext;
-                this._renderingCanvas = this._gl.canvas
 
-                if (this._gl.renderbufferStorageMultisample) {
-                    this._webGLVersion = 2.0;
-                }
+                // Context lost
+                if (!this._doNotHandleContextLost) {
+                    this._onContextLost = (evt: Event) => {
+                        evt.preventDefault();
+                        this._contextWasLost = true;
+                        Tools.Warn("WebGL context lost.");
 
-                options.stencil = this._gl.getContextAttributes().stencil;
-            }
+                        this.onContextLostObservable.notifyObservers(this);
+                    };
 
-            // Context lost
-            if (!this._doNotHandleContextLost) {
-                this._onContextLost = (evt: Event) => {
-                    evt.preventDefault();
-                    this._contextWasLost = true;
-                    Tools.Warn("WebGL context lost.");
+                    this._onContextRestored = (evt: Event) => {
+                        // Adding a timeout to avoid race condition at browser level
+                        setTimeout(()=> {
+                            // Rebuild gl context
+                            this._initGLContext();
 
-                    this.onContextLostObservable.notifyObservers(this);
-                };
+                            // Rebuild effects
+                            this._rebuildEffects();
 
-                this._onContextRestored = (evt: Event) => {
-                    // Rebuild gl context
-                    this._initGLContext();
+                            // Rebuild textures
+                            this._rebuildInternalTextures();
 
-                    // Rebuild effects
-                    this._rebuildEffects();
+                            // Rebuild buffers
+                            this._rebuildBuffers();
 
-                    // Rebuild textures
-                    this._rebuildInternalTextures();
+                            // Cache
+                            this.wipeCaches(true);
 
-                    // Rebuild buffers
-                    this._rebuildBuffers();
+                            Tools.Warn("WebGL context successfully restored.");
 
-                    // Cache
-                    this.wipeCaches(true);
+                            this.onContextRestoredObservable.notifyObservers(this);
 
-                    Tools.Warn("WebGL context successfully restored.");
+                            this._contextWasLost = false;
+                        }, 0);
+                    };
 
-                    this.onContextRestoredObservable.notifyObservers(this);
+                    canvas.addEventListener("webglcontextlost", this._onContextLost, false);
+                    canvas.addEventListener("webglcontextrestored", this._onContextRestored, false);
+                }                
+            } else {
+                this._gl = <WebGLRenderingContext>canvasOrContext;
+                this._renderingCanvas = this._gl.canvas
 
-                    this._contextWasLost = false;
-                };
+                if (this._gl.renderbufferStorageMultisample) {
+                    this._webGLVersion = 2.0;
+                }
 
-                canvas.addEventListener("webglcontextlost", this._onContextLost, false);
-                canvas.addEventListener("webglcontextrestored", this._onContextRestored, false);
+                options.stencil = this._gl.getContextAttributes().stencil;
             }
 
             // Viewport
@@ -1050,7 +1060,6 @@
             this._caps.uintIndices = this._webGLVersion > 1 || this._gl.getExtension('OES_element_index_uint') !== null;
             this._caps.fragmentDepthSupported = this._webGLVersion > 1 || this._gl.getExtension('EXT_frag_depth') !== null;
             this._caps.highPrecisionShaderSupported = true;
-            this._caps.drawBuffersExtension = this._webGLVersion > 1 || this._gl.getExtension('WEBGL_draw_buffers');
 
             // Checks if some of the format renders first to allow the use of webgl inspector.
             this._caps.colorBufferFloat = this._webGLVersion > 1 && this._gl.getExtension('EXT_color_buffer_float');
@@ -1068,6 +1077,36 @@
 
             this._caps.textureLOD = this._webGLVersion > 1 || this._gl.getExtension('EXT_shader_texture_lod');
 
+            // Draw buffers
+            if (this._webGLVersion > 1) {
+                this._caps.drawBuffersExtension = true;
+            } else {
+                var drawBuffersExtension = this._gl.getExtension('WEBGL_draw_buffers');
+
+                if (drawBuffersExtension !== null) {
+                    this._caps.drawBuffersExtension = true;
+                    this._gl.drawBuffers = drawBuffersExtension.drawBuffersWEBGL.bind(drawBuffersExtension);
+                    this._gl.DRAW_FRAMEBUFFER = this._gl.FRAMEBUFFER;
+                    
+                    for (var i = 0; i < 16; i++) {
+                        this._gl["COLOR_ATTACHMENT" + i + "_WEBGL"] = drawBuffersExtension["COLOR_ATTACHMENT" + i + "_WEBGL"];
+                    }
+                } else {
+                    this._caps.drawBuffersExtension = false;
+                }
+            }
+
+            // Depth Texture
+            if (this._webGLVersion > 1) {
+                this._caps.depthTextureExtension = true;
+            } else {
+                var depthTextureExtension = this._gl.getExtension('WEBGL_depth_texture');
+
+                if (depthTextureExtension != null) {
+                    this._caps.depthTextureExtension = true;
+                }
+            }
+
             // Vertex array object
             if (this._webGLVersion > 1) {
                 this._caps.vertexArrayObject = true;
@@ -1355,7 +1394,7 @@
 
             if (this._activeRenderLoops.length > 0) {
                 // Register new frame
-                Tools.QueueNewFrame(this._bindedRenderFunction, this._vrDisplayEnabled);
+                this._frameHandler = Tools.QueueNewFrame(this._bindedRenderFunction, this._vrDisplayEnabled);
             } else {
                 this._renderingQueueLaunched = false;
             }
@@ -1379,7 +1418,7 @@
             if (!this._renderingQueueLaunched) {
                 this._renderingQueueLaunched = true;
                 this._bindedRenderFunction = this._renderLoop.bind(this);
-                Tools.QueueNewFrame(this._bindedRenderFunction);
+                this._frameHandler = Tools.QueueNewFrame(this._bindedRenderFunction);
             }
         }
 
@@ -1602,7 +1641,6 @@
                 this.setSize(leftEye.renderWidth * 2, leftEye.renderHeight);
             } else {
                 //When the specs are implemented, need to uncomment this.
-                //this._vrDisplayEnabled.cancelAnimationFrame(this._vrAnimationFrameHandler);
                 this.setHardwareScalingLevel(this._oldHardwareScaleFactor);
                 this.setSize(this._oldSize.width, this._oldSize.height);
                 this._vrDisplayEnabled = undefined;
@@ -2520,6 +2558,11 @@
 
         public setColorWrite(enable: boolean): void {
             this._gl.colorMask(enable, enable, enable, enable);
+            this._colorWrite = enable;
+        }
+
+        public getColorWrite(): boolean {
+            return this._colorWrite;
         }
 
         public setAlphaConstants(r: number, g: number, b: number, a: number) {
@@ -3190,7 +3233,7 @@
 
             var width = size.width || size;
             var height = size.height || size;
-
+            
             var textures = [];
             var attachments = []
 
@@ -3216,7 +3259,8 @@
                 }
 
                 var texture = new InternalTexture(this, InternalTexture.DATASOURCE_MULTIRENDERTARGET);
-                var attachment = gl["COLOR_ATTACHMENT" + i];
+                var attachment = gl[this.webGLVersion > 1 ? "COLOR_ATTACHMENT" + i : "COLOR_ATTACHMENT" + i + "_WEBGL"];
+                
                 textures.push(texture);
                 attachments.push(attachment);
 
@@ -3256,7 +3300,7 @@
                 this._internalTexturesCache.push(texture);
             }
 
-            if (generateDepthTexture) {
+            if (generateDepthTexture && this._caps.depthTextureExtension) {
                 // Depth texture
                 var depthTexture = new InternalTexture(this, InternalTexture.DATASOURCE_MULTIRENDERTARGET);
 
@@ -3269,7 +3313,7 @@
                 gl.texImage2D(
                     gl.TEXTURE_2D,
                     0,
-                    gl.DEPTH_COMPONENT16,
+                    this.webGLVersion < 2 ? gl.DEPTH_COMPONENT : gl.DEPTH_COMPONENT16,
                     width,
                     height,
                     0,
@@ -4129,7 +4173,7 @@
 
                 if (internalTexture._cachedWrapU !== texture.wrapU) {
                     internalTexture._cachedWrapU = texture.wrapU;
-
+                    
                     switch (texture.wrapU) {
                         case Texture.WRAP_ADDRESSMODE:
                             this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_WRAP_S, this._gl.REPEAT);