Переглянути джерело

Merge remote-tracking branch 'origin/master' into ImageProcessing

Sebastien Vandenberghe 8 роки тому
батько
коміт
cbca56d98b
100 змінених файлів з 5514 додано та 3468 видалено
  1. 4 0
      Playground/debug.html
  2. 4 0
      Playground/index-local.html
  3. 4 0
      Playground/index.html
  4. 4 0
      Playground/index2_5.html
  5. 13 0
      Playground/js/index.js
  6. 1 0
      Playground/test.html
  7. BIN
      Playground/textures/fan.png
  8. BIN
      Playground/textures/lenscolor.png
  9. BIN
      Playground/textures/lensflaredirt.png
  10. BIN
      Playground/textures/lensstar.png
  11. 7 2
      Tools/Gulp/config.json
  12. 256 215
      dist/preview release/babylon.d.ts
  13. 41 82
      dist/preview release/babylon.js
  14. 601 286
      dist/preview release/babylon.max.js
  15. 256 215
      dist/preview release/babylon.module.d.ts
  16. 40 82
      dist/preview release/babylon.worker.js
  17. 794 758
      dist/preview release/customConfigurations/minimalViewer/babylon.d.ts
  18. 20 20
      dist/preview release/customConfigurations/minimalViewer/babylon.js
  19. 157 15
      dist/preview release/customConfigurations/minimalViewer/babylon.max.js
  20. 794 758
      dist/preview release/customConfigurations/minimalViewer/babylon.module.d.ts
  21. 1 1
      dist/preview release/gui/babylon.gui.min.js
  22. 263 263
      dist/preview release/inspector/babylon.inspector.bundle.js
  23. 30 1
      dist/preview release/inspector/babylon.inspector.d.ts
  24. 318 4
      dist/preview release/inspector/babylon.inspector.js
  25. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  26. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  27. 42 30
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  28. 319 200
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  29. 1 5
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  30. 42 30
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  31. 319 200
      dist/preview release/loaders/babylon.glTFFileLoader.js
  32. 2 7
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  33. 1 5
      dist/preview release/loaders/babylon.objFileLoader.min.js
  34. 1 0
      dist/preview release/materialsLibrary/babylon.cellMaterial.d.ts
  35. 7 0
      dist/preview release/materialsLibrary/babylon.cellMaterial.js
  36. 1 1
      dist/preview release/materialsLibrary/babylon.cellMaterial.min.js
  37. 1 1
      dist/preview release/materialsLibrary/babylon.customMaterial.min.js
  38. 1 0
      dist/preview release/materialsLibrary/babylon.fireMaterial.d.ts
  39. 13 0
      dist/preview release/materialsLibrary/babylon.fireMaterial.js
  40. 1 1
      dist/preview release/materialsLibrary/babylon.fireMaterial.min.js
  41. 1 0
      dist/preview release/materialsLibrary/babylon.furMaterial.d.ts
  42. 10 0
      dist/preview release/materialsLibrary/babylon.furMaterial.js
  43. 1 1
      dist/preview release/materialsLibrary/babylon.furMaterial.min.js
  44. 1 0
      dist/preview release/materialsLibrary/babylon.lavaMaterial.d.ts
  45. 7 0
      dist/preview release/materialsLibrary/babylon.lavaMaterial.js
  46. 1 1
      dist/preview release/materialsLibrary/babylon.lavaMaterial.min.js
  47. 1 0
      dist/preview release/materialsLibrary/babylon.normalMaterial.d.ts
  48. 7 0
      dist/preview release/materialsLibrary/babylon.normalMaterial.js
  49. 1 1
      dist/preview release/materialsLibrary/babylon.normalMaterial.min.js
  50. 1 0
      dist/preview release/materialsLibrary/babylon.simpleMaterial.d.ts
  51. 7 0
      dist/preview release/materialsLibrary/babylon.simpleMaterial.js
  52. 1 1
      dist/preview release/materialsLibrary/babylon.simpleMaterial.min.js
  53. 1 0
      dist/preview release/materialsLibrary/babylon.terrainMaterial.d.ts
  54. 25 0
      dist/preview release/materialsLibrary/babylon.terrainMaterial.js
  55. 1 1
      dist/preview release/materialsLibrary/babylon.terrainMaterial.min.js
  56. 1 0
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.d.ts
  57. 22 0
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.js
  58. 1 1
      dist/preview release/materialsLibrary/babylon.triPlanarMaterial.min.js
  59. 1 0
      dist/preview release/materialsLibrary/babylon.waterMaterial.d.ts
  60. 7 0
      dist/preview release/materialsLibrary/babylon.waterMaterial.js
  61. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  62. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  63. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  64. 3 1
      dist/preview release/what's new.md
  65. 3 0
      inspector/src/Inspector.ts
  66. 135 0
      inspector/src/adapters/GUIAdapter.ts
  67. 1 0
      inspector/src/lib.d.ts
  68. 1 1
      inspector/src/properties.ts
  69. 116 0
      inspector/src/properties_gui.ts
  70. 42 0
      inspector/src/tabs/GUITab.ts
  71. 1 0
      inspector/src/tabs/TabBar.ts
  72. 58 0
      inspector/test/index.js
  73. 5 2
      loaders/src/OBJ/babylon.objFileLoader.ts
  74. 3 1
      loaders/src/STL/babylon.stlFileLoader.ts
  75. 1 1
      loaders/src/glTF/1.0/babylon.glTFLoader.ts
  76. 54 0
      loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts
  77. 57 0
      loaders/src/glTF/2.0/Extensions/MSFT_lod.ts
  78. 226 160
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  79. 21 21
      loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts
  80. 4 7
      loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts
  81. 0 53
      loaders/src/glTF/2.0/babylon.glTFMaterialsPbrSpecularGlossinessExtension.ts
  82. 18 15
      loaders/src/glTF/babylon.glTFFileLoader.ts
  83. 10 0
      materialsLibrary/src/cell/babylon.cellMaterial.ts
  84. 18 0
      materialsLibrary/src/fire/babylon.fireMaterial.ts
  85. 14 0
      materialsLibrary/src/fur/babylon.furMaterial.ts
  86. 10 0
      materialsLibrary/src/lava/babylon.lavaMaterial.ts
  87. 10 0
      materialsLibrary/src/normal/babylon.normalMaterial.ts
  88. 10 0
      materialsLibrary/src/simple/babylon.simpleMaterial.ts
  89. 34 0
      materialsLibrary/src/terrain/babylon.terrainMaterial.ts
  90. 30 0
      materialsLibrary/src/triPlanar/babylon.triPlanarMaterial.ts
  91. 10 0
      materialsLibrary/src/water/babylon.waterMaterial.ts
  92. 5 1
      src/Materials/PBR/babylon.pbrBaseMaterial.ts
  93. 50 0
      src/Materials/PBR/babylon.pbrMaterial.ts
  94. 17 0
      src/Materials/PBR/babylon.pbrMetallicRoughnessMaterial.ts
  95. 17 0
      src/Materials/PBR/babylon.pbrSpecularGlossinessMaterial.ts
  96. 41 0
      src/Materials/Textures/babylon.baseTexture.ts
  97. 7 7
      src/Materials/Textures/babylon.texture.ts
  98. 12 2
      src/Materials/babylon.material.ts
  99. 5 0
      src/Materials/babylon.materialHelper.ts
  100. 0 0
      src/Materials/babylon.multiMaterial.ts

+ 4 - 0
Playground/debug.html

@@ -127,6 +127,7 @@
                     <div class="option checked" id="editorButton1600">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton1600">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton1600">Editor Fullscreen</div>
                     <div class="option" id="formatButton1600">Format code</div>
                 </div>
             </div>
@@ -202,6 +203,7 @@
                     <div class="option checked" id="editorButton1475">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton1475">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton1475">Editor Fullscreen</div>
                     <div class="option" id="formatButton1475">Format code</div>
                     <div class="option" id="debugButton1475">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option" id="metadataButton1475">Metadata</div>
@@ -267,6 +269,7 @@
                     <div class="option checked" id="editorButton1030">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton1030">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton1030">Editor Fullscreen</div>
                     <div class="option" id="formatButton1030">Format code</div>
                     <div class="option" id="debugButton1030">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option" id="metadataButton1030">Metadata</div>
@@ -329,6 +332,7 @@
                     <div style="display:none;" class="option checked" id="editorButton750">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton750">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton750">Editor Fullscreen</div>
                     <div class="option" id="formatButton750">Format code</div>
                     <div class="option" id="debugButton750">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option" id="metadataButton750">Metadata</div>

+ 4 - 0
Playground/index-local.html

@@ -69,6 +69,7 @@
                     <div class="option checked" id="editorButton1600">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton1600">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton1600">Editor Fullscreen</div>
                     <div class="option" id="formatButton1600">Format code</div>
                 </div>
             </div>
@@ -143,6 +144,7 @@
                     <div class="option checked" id="editorButton1475">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton1475">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton1475">Editor Fullscreen</div>
                     <div class="option" id="formatButton1475">Format code</div>
                     <div class="option" id="debugButton1475">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option" id="metadataButton1475">Metadata</div>
@@ -208,6 +210,7 @@
                     <div class="option checked" id="editorButton1030">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton1030">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton1030">Editor Fullscreen</div>
                     <div class="option" id="formatButton1030">Format code</div>
                     <div class="option" id="debugButton1030">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option" id="metadataButton1030">Metadata</div>
@@ -270,6 +273,7 @@
                     <div style="display:none;" class="option checked" id="editorButton750">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton750">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton750">Editor Fullscreen</div>
                     <div class="option" id="formatButton750">Format code</div>
                     <div class="option" id="debugButton750">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option" id="metadataButton750">Metadata</div>

+ 4 - 0
Playground/index.html

@@ -125,6 +125,7 @@
                     <div class="option checked" id="editorButton1600">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton1600">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton1600">Editor Fullscreen</div>
                     <div class="option" id="formatButton1600">Format code</div>
                 </div>
             </div>
@@ -199,6 +200,7 @@
                     <div class="option checked" id="editorButton1475">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton1475">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton1475">Editor Fullscreen</div>
                     <div class="option" id="formatButton1475">Format code</div>
                     <div class="option" id="debugButton1475">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option" id="metadataButton1475">Metadata</div>
@@ -264,6 +266,7 @@
                     <div class="option checked" id="editorButton1030">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton1030">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton1030">Editor Fullscreen</div>
                     <div class="option" id="formatButton1030">Format code</div>
                     <div class="option" id="debugButton1030">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option" id="metadataButton1030">Metadata</div>
@@ -326,6 +329,7 @@
                     <div style="display:none;" class="option checked" id="editorButton750">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton750">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton750">Editor Fullscreen</div>
                     <div class="option" id="formatButton750">Format code</div>
                     <div class="option" id="debugButton750">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option" id="metadataButton750">Metadata</div>

+ 4 - 0
Playground/index2_5.html

@@ -97,6 +97,7 @@
                     <div class="option checked" id="editorButton1600">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton1600">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton1600">Editor Fullscreen</div>
                     <div class="option" id="formatButton1600">Format code</div>
                 </div>
             </div>
@@ -172,6 +173,7 @@
                     <div class="option checked" id="editorButton1475">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton1475">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton1475">Editor Fullscreen</div>
                     <div class="option" id="formatButton1475">Format code</div>
                     <div class="option" id="debugButton1475">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option" id="metadataButton1475">Metadata</div>
@@ -237,6 +239,7 @@
                     <div class="option checked" id="editorButton1030">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton1030">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton1030">Editor Fullscreen</div>
                     <div class="option" id="formatButton1030">Format code</div>
                     <div class="option" id="debugButton1030">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option" id="metadataButton1030">Metadata</div>
@@ -299,6 +302,7 @@
                     <div style="display:none;" class="option checked" id="editorButton750">Editor <i class="fa fa-check-square" aria-hidden="true"></i>
                     </div>
                     <div class="option" id="fullscreenButton750">Fullscreen</div>
+                    <div class="option" id="editorFullscreenButton750">Editor Fullscreen</div>
                     <div class="option" id="formatButton750">Format code</div>
                     <div class="option" id="debugButton750">Debug layer<i class="fa fa-square-o" aria-hidden="true"></i></div>
                     <div class="option" id="metadataButton750">Metadata</div>

+ 13 - 0
Playground/js/index.js

@@ -586,6 +586,17 @@
                 engine.switchFullscreen(true);
             }
         }
+        var editorGoFullscreen = function () {
+            var editorDiv = document.getElementById("jsEditor");
+            if (editorDiv.requestFullscreen) {
+            editorDiv.requestFullscreen();
+            } else if (editorDiv.mozRequestFullScreen) {
+            editorDiv.mozRequestFullScreen();
+            } else if (editorDiv.webkitRequestFullscreen) {
+            editorDiv.webkitRequestFullscreen();
+            }
+
+        }
 
         var toggleEditor = function () {
             var editorButton = document.getElementById("editorButton1600");
@@ -887,6 +898,8 @@
         setToMultipleID("editorButton", "click", toggleEditor);
         // FullScreen
         setToMultipleID("fullscreenButton", "click", goFullscreen);
+        // Editor fullScreen
+        setToMultipleID("editorFullscreenButton", "click", editorGoFullscreen);
         // Format
         setToMultipleID("formatButton", "click", formatCode);
         // Debug

+ 1 - 0
Playground/test.html

@@ -41,6 +41,7 @@
     </div>
     <div class="btn-group pull-right">
         <button class="btn" id="fullscreenButton">Fullscreen</button>
+        <button class="btn" id="editorFullscreenButton">Editor Fullscreen</button>
     </div>
     <div class="btn-group pull-right">
         <a class="btn dropdown-toggle" data-toggle="dropdown" href="#">

BIN
Playground/textures/fan.png


BIN
Playground/textures/lenscolor.png


BIN
Playground/textures/lensflaredirt.png


BIN
Playground/textures/lensstar.png


+ 7 - 2
Tools/Gulp/config.json

@@ -1338,7 +1338,8 @@
                     "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderUtils.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
-                    "../../loaders/src/glTF/2.0/babylon.glTFMaterialsPbrSpecularGlossinessExtension.ts"
+                    "../../loaders/src/glTF/2.0/Extensions/MSFT_lod.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts"
                 ],
                 "output": "babylon.glTF2FileLoader.js"
             },
@@ -1355,7 +1356,8 @@
                     "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderUtils.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
-                    "../../loaders/src/glTF/2.0/babylon.glTFMaterialsPbrSpecularGlossinessExtension.ts"
+                    "../../loaders/src/glTF/2.0/Extensions/MSFT_lod.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts"
                 ],
                 "output": "babylon.glTFFileLoader.js"
             }
@@ -1415,9 +1417,11 @@
                 "files": [
                     "../../inspector/src/Inspector.ts",
                     "../../inspector/src/properties.ts",
+                    "../../inspector/src/properties_gui.ts",
                     "../../inspector/src/gui/BasicElement.ts",
                     "../../inspector/src/adapters/Adapter.ts",
                     "../../inspector/src/adapters/CameraAdapter.ts",
+                    "../../inspector/src/adapters/GUIAdapter.ts",
                     "../../inspector/src/adapters/SoundAdapter.ts",
                     "../../inspector/src/adapters/TextureAdapter.ts",
                     "../../inspector/src/adapters/LightAdapter.ts",
@@ -1437,6 +1441,7 @@
                     "../../inspector/src/tabs/Tab.ts",
                     "../../inspector/src/tabs/PropertyTab.ts",
                     "../../inspector/src/tabs/CameraTab.ts",
+                    "../../inspector/src/tabs/GUITab.ts",
                     "../../inspector/src/tabs/SoundTab.ts",
                     "../../inspector/src/tabs/TextureTab.ts",
                     "../../inspector/src/tabs/LightTab.ts",

+ 256 - 215
dist/preview release/babylon.d.ts

@@ -241,6 +241,7 @@ declare module BABYLON {
         private _textureUnits;
         private _workingCanvas;
         private _workingContext;
+        private _dummyFramebuffer;
         private _externalData;
         private _bindedRenderFunction;
         private _vaoRecordInProgress;
@@ -570,6 +571,7 @@ declare module BABYLON {
         getFps(): number;
         getDeltaTime(): number;
         private _measureFps();
+        _readTexturePixels(texture: WebGLTexture, width: number, height: number, faceIndex?: number): Uint8Array;
         private _canRenderToFloatFramebuffer();
         private _canRenderToHalfFloatFramebuffer();
         private _canRenderToFramebuffer(type);
@@ -4023,120 +4025,6 @@ declare module BABYLON {
     }
 }
 
-declare module BABYLON {
-    class BoundingBox implements ICullable {
-        minimum: Vector3;
-        maximum: Vector3;
-        vectors: Vector3[];
-        center: Vector3;
-        centerWorld: Vector3;
-        extendSize: Vector3;
-        extendSizeWorld: Vector3;
-        directions: Vector3[];
-        vectorsWorld: Vector3[];
-        minimumWorld: Vector3;
-        maximumWorld: Vector3;
-        private _worldMatrix;
-        constructor(minimum: Vector3, maximum: Vector3);
-        getWorldMatrix(): Matrix;
-        setWorldMatrix(matrix: Matrix): BoundingBox;
-        _update(world: Matrix): void;
-        isInFrustum(frustumPlanes: Plane[]): boolean;
-        isCompletelyInFrustum(frustumPlanes: Plane[]): boolean;
-        intersectsPoint(point: Vector3): boolean;
-        intersectsSphere(sphere: BoundingSphere): boolean;
-        intersectsMinMax(min: Vector3, max: Vector3): boolean;
-        static Intersects(box0: BoundingBox, box1: BoundingBox): boolean;
-        static IntersectsSphere(minPoint: Vector3, maxPoint: Vector3, sphereCenter: Vector3, sphereRadius: number): boolean;
-        static IsCompletelyInFrustum(boundingVectors: Vector3[], frustumPlanes: Plane[]): boolean;
-        static IsInFrustum(boundingVectors: Vector3[], frustumPlanes: Plane[]): boolean;
-    }
-}
-
-declare module BABYLON {
-    interface ICullable {
-        isInFrustum(frustumPlanes: Plane[]): boolean;
-        isCompletelyInFrustum(frustumPlanes: Plane[]): boolean;
-    }
-    class BoundingInfo implements ICullable {
-        minimum: Vector3;
-        maximum: Vector3;
-        boundingBox: BoundingBox;
-        boundingSphere: BoundingSphere;
-        private _isLocked;
-        constructor(minimum: Vector3, maximum: Vector3);
-        isLocked: boolean;
-        update(world: Matrix): void;
-        isInFrustum(frustumPlanes: Plane[]): boolean;
-        isCompletelyInFrustum(frustumPlanes: Plane[]): boolean;
-        _checkCollision(collider: Collider): boolean;
-        intersectsPoint(point: Vector3): boolean;
-        intersects(boundingInfo: BoundingInfo, precise: boolean): boolean;
-    }
-}
-
-declare module BABYLON {
-    class BoundingSphere {
-        minimum: Vector3;
-        maximum: Vector3;
-        center: Vector3;
-        radius: number;
-        centerWorld: Vector3;
-        radiusWorld: number;
-        private _tempRadiusVector;
-        constructor(minimum: Vector3, maximum: Vector3);
-        _update(world: Matrix): void;
-        isInFrustum(frustumPlanes: Plane[]): boolean;
-        intersectsPoint(point: Vector3): boolean;
-        static Intersects(sphere0: BoundingSphere, sphere1: BoundingSphere): boolean;
-    }
-}
-
-declare module BABYLON {
-    class Ray {
-        origin: Vector3;
-        direction: Vector3;
-        length: number;
-        private _edge1;
-        private _edge2;
-        private _pvec;
-        private _tvec;
-        private _qvec;
-        private _tmpRay;
-        private _rayHelper;
-        constructor(origin: Vector3, direction: Vector3, length?: number);
-        intersectsBoxMinMax(minimum: Vector3, maximum: Vector3): boolean;
-        intersectsBox(box: BoundingBox): boolean;
-        intersectsSphere(sphere: BoundingSphere): boolean;
-        intersectsTriangle(vertex0: Vector3, vertex1: Vector3, vertex2: Vector3): IntersectionInfo;
-        intersectsPlane(plane: Plane): number;
-        intersectsMesh(mesh: AbstractMesh, fastCheck?: boolean): PickingInfo;
-        intersectsMeshes(meshes: Array<AbstractMesh>, fastCheck?: boolean, results?: Array<PickingInfo>): Array<PickingInfo>;
-        private _comparePickingInfo(pickingInfoA, pickingInfoB);
-        private static smallnum;
-        private static rayl;
-        /**
-         * Intersection test between the ray and a given segment whithin a given tolerance (threshold)
-         * @param sega the first point of the segment to test the intersection against
-         * @param segb the second point of the segment to test the intersection against
-         * @param threshold the tolerance margin, if the ray doesn't intersect the segment but is close to the given threshold, the intersection is successful
-         * @return the distance from the ray origin to the intersection point if there's intersection, or -1 if there's no intersection
-         */
-        intersectionSegment(sega: Vector3, segb: Vector3, threshold: number): number;
-        static CreateNew(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Ray;
-        /**
-        * Function will create a new transformed ray starting from origin and ending at the end point. Ray's length will be set, and ray will be
-        * transformed to the given world matrix.
-        * @param origin The origin point
-        * @param end The end point
-        * @param world a matrix to transform the ray to. Default is the identity matrix.
-        */
-        static CreateNewFromTo(origin: Vector3, end: Vector3, world?: Matrix): Ray;
-        static Transform(ray: Ray, matrix: Matrix): Ray;
-        static TransformToRef(ray: Ray, matrix: Matrix, result: Ray): void;
-    }
-}
-
 declare module BABYLON.Debug {
     class AxesViewer {
         private _xline;
@@ -4499,6 +4387,120 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    class BoundingBox implements ICullable {
+        minimum: Vector3;
+        maximum: Vector3;
+        vectors: Vector3[];
+        center: Vector3;
+        centerWorld: Vector3;
+        extendSize: Vector3;
+        extendSizeWorld: Vector3;
+        directions: Vector3[];
+        vectorsWorld: Vector3[];
+        minimumWorld: Vector3;
+        maximumWorld: Vector3;
+        private _worldMatrix;
+        constructor(minimum: Vector3, maximum: Vector3);
+        getWorldMatrix(): Matrix;
+        setWorldMatrix(matrix: Matrix): BoundingBox;
+        _update(world: Matrix): void;
+        isInFrustum(frustumPlanes: Plane[]): boolean;
+        isCompletelyInFrustum(frustumPlanes: Plane[]): boolean;
+        intersectsPoint(point: Vector3): boolean;
+        intersectsSphere(sphere: BoundingSphere): boolean;
+        intersectsMinMax(min: Vector3, max: Vector3): boolean;
+        static Intersects(box0: BoundingBox, box1: BoundingBox): boolean;
+        static IntersectsSphere(minPoint: Vector3, maxPoint: Vector3, sphereCenter: Vector3, sphereRadius: number): boolean;
+        static IsCompletelyInFrustum(boundingVectors: Vector3[], frustumPlanes: Plane[]): boolean;
+        static IsInFrustum(boundingVectors: Vector3[], frustumPlanes: Plane[]): boolean;
+    }
+}
+
+declare module BABYLON {
+    interface ICullable {
+        isInFrustum(frustumPlanes: Plane[]): boolean;
+        isCompletelyInFrustum(frustumPlanes: Plane[]): boolean;
+    }
+    class BoundingInfo implements ICullable {
+        minimum: Vector3;
+        maximum: Vector3;
+        boundingBox: BoundingBox;
+        boundingSphere: BoundingSphere;
+        private _isLocked;
+        constructor(minimum: Vector3, maximum: Vector3);
+        isLocked: boolean;
+        update(world: Matrix): void;
+        isInFrustum(frustumPlanes: Plane[]): boolean;
+        isCompletelyInFrustum(frustumPlanes: Plane[]): boolean;
+        _checkCollision(collider: Collider): boolean;
+        intersectsPoint(point: Vector3): boolean;
+        intersects(boundingInfo: BoundingInfo, precise: boolean): boolean;
+    }
+}
+
+declare module BABYLON {
+    class BoundingSphere {
+        minimum: Vector3;
+        maximum: Vector3;
+        center: Vector3;
+        radius: number;
+        centerWorld: Vector3;
+        radiusWorld: number;
+        private _tempRadiusVector;
+        constructor(minimum: Vector3, maximum: Vector3);
+        _update(world: Matrix): void;
+        isInFrustum(frustumPlanes: Plane[]): boolean;
+        intersectsPoint(point: Vector3): boolean;
+        static Intersects(sphere0: BoundingSphere, sphere1: BoundingSphere): boolean;
+    }
+}
+
+declare module BABYLON {
+    class Ray {
+        origin: Vector3;
+        direction: Vector3;
+        length: number;
+        private _edge1;
+        private _edge2;
+        private _pvec;
+        private _tvec;
+        private _qvec;
+        private _tmpRay;
+        private _rayHelper;
+        constructor(origin: Vector3, direction: Vector3, length?: number);
+        intersectsBoxMinMax(minimum: Vector3, maximum: Vector3): boolean;
+        intersectsBox(box: BoundingBox): boolean;
+        intersectsSphere(sphere: BoundingSphere): boolean;
+        intersectsTriangle(vertex0: Vector3, vertex1: Vector3, vertex2: Vector3): IntersectionInfo;
+        intersectsPlane(plane: Plane): number;
+        intersectsMesh(mesh: AbstractMesh, fastCheck?: boolean): PickingInfo;
+        intersectsMeshes(meshes: Array<AbstractMesh>, fastCheck?: boolean, results?: Array<PickingInfo>): Array<PickingInfo>;
+        private _comparePickingInfo(pickingInfoA, pickingInfoB);
+        private static smallnum;
+        private static rayl;
+        /**
+         * Intersection test between the ray and a given segment whithin a given tolerance (threshold)
+         * @param sega the first point of the segment to test the intersection against
+         * @param segb the second point of the segment to test the intersection against
+         * @param threshold the tolerance margin, if the ray doesn't intersect the segment but is close to the given threshold, the intersection is successful
+         * @return the distance from the ray origin to the intersection point if there's intersection, or -1 if there's no intersection
+         */
+        intersectionSegment(sega: Vector3, segb: Vector3, threshold: number): number;
+        static CreateNew(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Ray;
+        /**
+        * Function will create a new transformed ray starting from origin and ending at the end point. Ray's length will be set, and ray will be
+        * transformed to the given world matrix.
+        * @param origin The origin point
+        * @param end The end point
+        * @param world a matrix to transform the ray to. Default is the identity matrix.
+        */
+        static CreateNewFromTo(origin: Vector3, end: Vector3, world?: Matrix): Ray;
+        static Transform(ray: Ray, matrix: Matrix): Ray;
+        static TransformToRef(ray: Ray, matrix: Matrix, result: Ray): void;
+    }
+}
+
+declare module BABYLON {
     class LensFlare {
         size: number;
         position: number;
@@ -5077,61 +5079,6 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
-    interface ISceneLoaderPluginExtensions {
-        [extension: string]: {
-            isBinary: boolean;
-        };
-    }
-    interface ISceneLoaderPlugin {
-        extensions: string | ISceneLoaderPluginExtensions;
-        importMesh: (meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => boolean;
-        load: (scene: Scene, data: string, rootUrl: string) => boolean;
-        canDirectLoad?: (data: string) => boolean;
-    }
-    interface ISceneLoaderPluginAsync {
-        extensions: string | ISceneLoaderPluginExtensions;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: any, rootUrl: string, onsuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror: () => void) => void;
-        loadAsync: (scene: Scene, data: string, rootUrl: string, onsuccess: () => void, onerror: () => void) => void;
-        canDirectLoad?: (data: string) => boolean;
-    }
-    class SceneLoader {
-        private static _ForceFullSceneLoadingForIncremental;
-        private static _ShowLoadingScreen;
-        static readonly NO_LOGGING: number;
-        static readonly MINIMAL_LOGGING: number;
-        static readonly SUMMARY_LOGGING: number;
-        static readonly DETAILED_LOGGING: number;
-        private static _loggingLevel;
-        static ForceFullSceneLoadingForIncremental: boolean;
-        static ShowLoadingScreen: boolean;
-        static loggingLevel: number;
-        private static _registeredPlugins;
-        private static _getDefaultPlugin();
-        private static _getPluginForExtension(extension);
-        private static _getPluginForDirectLoad(data);
-        private static _getPluginForFilename(sceneFilename);
-        private static _getDirectLoad(sceneFilename);
-        static GetPluginForExtension(extension: string): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
-        static RegisterPlugin(plugin: ISceneLoaderPlugin | ISceneLoaderPluginAsync): void;
-        static ImportMesh(meshesNames: any, rootUrl: string, sceneFilename: string, scene: Scene, onsuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, progressCallBack?: () => void, onerror?: (scene: Scene, message: string, exception?: any) => void): void;
-        /**
-        * Load a scene
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
-        * @param engine is the instance of BABYLON.Engine to use to create the scene
-        */
-        static Load(rootUrl: string, sceneFilename: any, engine: Engine, onsuccess?: (scene: Scene) => void, progressCallBack?: any, onerror?: (scene: Scene) => void): void;
-        /**
-        * Append a scene
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
-        * @param scene is the instance of BABYLON.Scene to append to
-        */
-        static Append(rootUrl: string, sceneFilename: any, scene: Scene, onsuccess?: (scene: Scene) => void, progressCallBack?: any, onerror?: (scene: Scene) => void): void;
-    }
-}
-
-declare module BABYLON {
     /**
      * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT).
      * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
@@ -5626,9 +5573,12 @@ declare module BABYLON {
         bindViewProjection(effect: Effect): void;
         protected _afterBind(mesh: Mesh): void;
         unbind(): void;
+        getActiveTextures(): BaseTexture[];
         clone(name: string): Material;
         getBindedMeshes(): AbstractMesh[];
-        forceCompilation(mesh: AbstractMesh, onCompiled: (material: Material) => void): void;
+        forceCompilation(mesh: AbstractMesh, onCompiled: (material: Material) => void, options: {
+            alphaTest: boolean;
+        }): void;
         markAsDirty(flag: number): void;
         protected _markAllSubMeshesAsDirty(func: (defines: MaterialDefines) => void): void;
         protected _markAllSubMeshesAsTexturesDirty(): void;
@@ -5672,6 +5622,7 @@ declare module BABYLON {
         constructor(name: string, scene: Scene);
         private _hookArray(array);
         getSubMaterial(index: any): Material;
+        getActiveTextures(): BaseTexture[];
         getClassName(): string;
         isReady(mesh?: AbstractMesh): boolean;
         clone(name: string, cloneChildren?: boolean): MultiMaterial;
@@ -5733,6 +5684,7 @@ declare module BABYLON {
         isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
         bindOnlyWorldMatrix(world: Matrix): void;
         bind(world: Matrix, mesh?: Mesh): void;
+        getActiveTextures(): BaseTexture[];
         clone(name: string): ShaderMaterial;
         dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean): void;
         serialize(): any;
@@ -5921,6 +5873,7 @@ declare module BABYLON {
         unbind(): void;
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
+        getActiveTextures(): BaseTexture[];
         dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean): void;
         clone(name: string): StandardMaterial;
         serialize(): any;
@@ -8254,6 +8207,61 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    interface ISceneLoaderPluginExtensions {
+        [extension: string]: {
+            isBinary: boolean;
+        };
+    }
+    interface ISceneLoaderPlugin {
+        extensions: string | ISceneLoaderPluginExtensions;
+        importMesh: (meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => boolean;
+        load: (scene: Scene, data: string, rootUrl: string) => boolean;
+        canDirectLoad?: (data: string) => boolean;
+    }
+    interface ISceneLoaderPluginAsync {
+        extensions: string | ISceneLoaderPluginExtensions;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: any, rootUrl: string, onsuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror: () => void) => void;
+        loadAsync: (scene: Scene, data: string, rootUrl: string, onsuccess: () => void, onerror: () => void) => void;
+        canDirectLoad?: (data: string) => boolean;
+    }
+    class SceneLoader {
+        private static _ForceFullSceneLoadingForIncremental;
+        private static _ShowLoadingScreen;
+        static readonly NO_LOGGING: number;
+        static readonly MINIMAL_LOGGING: number;
+        static readonly SUMMARY_LOGGING: number;
+        static readonly DETAILED_LOGGING: number;
+        private static _loggingLevel;
+        static ForceFullSceneLoadingForIncremental: boolean;
+        static ShowLoadingScreen: boolean;
+        static loggingLevel: number;
+        private static _registeredPlugins;
+        private static _getDefaultPlugin();
+        private static _getPluginForExtension(extension);
+        private static _getPluginForDirectLoad(data);
+        private static _getPluginForFilename(sceneFilename);
+        private static _getDirectLoad(sceneFilename);
+        static GetPluginForExtension(extension: string): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
+        static RegisterPlugin(plugin: ISceneLoaderPlugin | ISceneLoaderPluginAsync): void;
+        static ImportMesh(meshesNames: any, rootUrl: string, sceneFilename: string, scene: Scene, onsuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, progressCallBack?: () => void, onerror?: (scene: Scene, message: string, exception?: any) => void): void;
+        /**
+        * Load a scene
+        * @param rootUrl a string that defines the root url for scene and resources
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param engine is the instance of BABYLON.Engine to use to create the scene
+        */
+        static Load(rootUrl: string, sceneFilename: any, engine: Engine, onsuccess?: (scene: Scene) => void, progressCallBack?: any, onerror?: (scene: Scene) => void): void;
+        /**
+        * Append a scene
+        * @param rootUrl a string that defines the root url for scene and resources
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param scene is the instance of BABYLON.Scene to append to
+        */
+        static Append(rootUrl: string, sceneFilename: any, scene: Scene, onsuccess?: (scene: Scene) => void, progressCallBack?: any, onerror?: (scene: Scene) => void): void;
+    }
+}
+
+declare module BABYLON {
     class AbstractMesh extends Node implements IDisposable, ICullable, IGetSetVerticesData {
         private static _BILLBOARDMODE_NONE;
         private static _BILLBOARDMODE_X;
@@ -12479,6 +12487,36 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    class ReflectionProbe {
+        name: string;
+        private _scene;
+        private _renderTargetTexture;
+        private _projectionMatrix;
+        private _viewMatrix;
+        private _target;
+        private _add;
+        private _attachedMesh;
+        invertYAxis: boolean;
+        position: Vector3;
+        constructor(name: string, size: number, scene: Scene, generateMipMaps?: boolean);
+        samples: number;
+        refreshRate: number;
+        getScene(): Scene;
+        readonly cubeTexture: RenderTargetTexture;
+        readonly renderList: AbstractMesh[];
+        attachToMesh(mesh: AbstractMesh): void;
+        /**
+         * Specifies whether or not the stencil and depth buffer are cleared between two rendering groups.
+         *
+         * @param renderingGroupId The rendering group id corresponding to its index
+         * @param autoClearDepthStencil Automatically clears depth and stencil between groups if true.
+         */
+        setRenderingAutoClearDepthStencil(renderingGroupId: number, autoClearDepthStencil: boolean): void;
+        dispose(): void;
+    }
+}
+
+declare module BABYLON {
     class AnaglyphPostProcess extends PostProcess {
         private _passedProcess;
         constructor(name: string, options: number | PostProcessOptions, rigCameras: Camera[], samplingMode?: number, engine?: Engine, reusable?: boolean);
@@ -12884,36 +12922,6 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
-    class ReflectionProbe {
-        name: string;
-        private _scene;
-        private _renderTargetTexture;
-        private _projectionMatrix;
-        private _viewMatrix;
-        private _target;
-        private _add;
-        private _attachedMesh;
-        invertYAxis: boolean;
-        position: Vector3;
-        constructor(name: string, size: number, scene: Scene, generateMipMaps?: boolean);
-        samples: number;
-        refreshRate: number;
-        getScene(): Scene;
-        readonly cubeTexture: RenderTargetTexture;
-        readonly renderList: AbstractMesh[];
-        attachToMesh(mesh: AbstractMesh): void;
-        /**
-         * Specifies whether or not the stencil and depth buffer are cleared between two rendering groups.
-         *
-         * @param renderingGroupId The rendering group id corresponding to its index
-         * @param autoClearDepthStencil Automatically clears depth and stencil between groups if true.
-         */
-        setRenderingAutoClearDepthStencil(renderingGroupId: number, autoClearDepthStencil: boolean): void;
-        dispose(): void;
-    }
-}
-
-declare module BABYLON {
     class BoundingBoxRenderer {
         frontColor: Color3;
         backColor: Color3;
@@ -12978,17 +12986,21 @@ declare module BABYLON {
         private _scene;
         private _multiRenderTarget;
         private _effect;
+        private _ratio;
         private _viewMatrix;
         private _projectionMatrix;
         private _transformMatrix;
         private _worldViewProjection;
         private _cachedDefines;
+        private _enablePosition;
         renderList: Mesh[];
         readonly isSupported: boolean;
+        enablePosition: boolean;
         constructor(scene: Scene, ratio?: number);
         isReady(subMesh: SubMesh, useInstances: boolean): boolean;
         getGBuffer(): MultiRenderTarget;
         dispose(): void;
+        private _createRenderTargets();
     }
 }
 
@@ -15229,9 +15241,6 @@ declare module BABYLON {
     }
 }
 
-declare module BABYLON.Internals {
-}
-
 declare module BABYLON {
     /**
      * The Physically based material base class of BJS.
@@ -15240,7 +15249,7 @@ declare module BABYLON {
      * For more information, please refer to the documentation :
      * http://doc.babylonjs.com/extensions/Physically_Based_Rendering
      */
-    abstract class PBRBaseMaterial extends BABYLON.PushMaterial {
+    abstract class PBRBaseMaterial extends PushMaterial {
         /**
          * Intensity of the direct lights e.g. the four lights available in your scene.
          * This impacts both the direct diffuse and specular highlights.
@@ -15840,6 +15849,7 @@ declare module BABYLON {
          */
         constructor(name: string, scene: Scene);
         getClassName(): string;
+        getActiveTextures(): BaseTexture[];
         clone(name: string): PBRMaterial;
         serialize(): any;
         static Parse(source: any, scene: Scene, rootUrl: string): PBRMaterial;
@@ -15893,6 +15903,10 @@ declare module BABYLON {
          */
         getClassName(): string;
         /**
+         * Return the active textures of the material.
+         */
+        getActiveTextures(): BaseTexture[];
+        /**
          * Serialize the material to a parsable JSON object.
          */
         serialize(): any;
@@ -15944,6 +15958,10 @@ declare module BABYLON {
          */
         getClassName(): string;
         /**
+         * Return the active textures of the material.
+         */
+        getActiveTextures(): BaseTexture[];
+        /**
          * Serialize the material to a parsable JSON object.
          */
         serialize(): any;
@@ -16001,9 +16019,11 @@ declare module BABYLON {
         _getFromCache(url: string, noMipmap: boolean, sampling?: number): WebGLTexture;
         delayLoad(): void;
         clone(): BaseTexture;
+        readPixels(faceIndex?: number): Uint8Array;
         releaseInternalTexture(): void;
         dispose(): void;
         serialize(): any;
+        static WhenAllReady(textures: BaseTexture[], onLoad: () => void): void;
     }
 }
 
@@ -16510,7 +16530,7 @@ declare module BABYLON {
         protected _format: number;
         private _delayedOnLoad;
         private _delayedOnError;
-        private _onLoadObservarble;
+        private _onLoadObservable;
         protected _isBlocking: boolean;
         isBlocking: boolean;
         constructor(url: string, scene: Scene, noMipmap?: boolean, invertY?: boolean, samplingMode?: number, onLoad?: () => void, onError?: () => void, buffer?: any, deleteBuffer?: boolean, format?: number);
@@ -16521,7 +16541,7 @@ declare module BABYLON {
         getTextureMatrix(): Matrix;
         getReflectionTextureMatrix(): Matrix;
         clone(): Texture;
-        readonly onLoadObservable: Observable<boolean>;
+        readonly onLoadObservable: Observable<Texture>;
         static CreateFromBase64String(data: string, name: string, scene: Scene, noMipmap?: boolean, invertY?: boolean, samplingMode?: number, onLoad?: () => void, onError?: () => void, format?: number): Texture;
         static Parse(parsedTexture: any, scene: Scene, rootUrl: string): BaseTexture;
         static LoadFromDataString(name: string, buffer: any, scene: Scene, deleteBuffer?: boolean, noMipmap?: boolean, invertY?: boolean, samplingMode?: number, onLoad?: () => void, onError?: () => void, format?: number): Texture;
@@ -16559,6 +16579,9 @@ declare module BABYLON {
     }
 }
 
+declare module BABYLON.Internals {
+}
+
 declare module BABYLON {
     class CannonJSPlugin implements IPhysicsEnginePlugin {
         private _useDeltaForWorldStep;
@@ -17399,9 +17422,14 @@ declare module BABYLON {
         originalPostProcess: PostProcess;
         downSampleX4PostProcess: PostProcess;
         brightPassPostProcess: PostProcess;
-        gaussianBlurHPostProcesses: PostProcess[];
-        gaussianBlurVPostProcesses: PostProcess[];
+        blurHPostProcesses: PostProcess[];
+        blurVPostProcesses: PostProcess[];
         textureAdderPostProcess: PostProcess;
+        volumetricLightPostProcess: PostProcess;
+        volumetricLightSmoothXPostProcess: BlurPostProcess;
+        volumetricLightSmoothYPostProcess: BlurPostProcess;
+        volumetricLightMergePostProces: PostProcess;
+        volumetricLightFinalPostProcess: PostProcess;
         luminancePostProcess: PostProcess;
         luminanceDownSamplePostProcesses: PostProcess[];
         hdrPostProcess: PostProcess;
@@ -17415,11 +17443,12 @@ declare module BABYLON {
         brightThreshold: number;
         blurWidth: number;
         horizontalBlur: boolean;
-        gaussianCoefficient: number;
-        gaussianMean: number;
-        gaussianStandardDeviation: number;
         exposure: number;
         lensTexture: Texture;
+        volumetricLightCoefficient: number;
+        volumetricLightPower: number;
+        volumetricLightBlurScale: number;
+        sourceLight: SpotLight | DirectionalLight;
         hdrMinimumLuminance: number;
         hdrDecreaseRate: number;
         hdrIncreaseRate: number;
@@ -17438,21 +17467,26 @@ declare module BABYLON {
         * Private members
         */
         private _scene;
-        private _depthRenderer;
         private _currentDepthOfFieldSource;
-        private _currentHDRSource;
+        private _basePostProcess;
         private _hdrCurrentLuminance;
-        private _motionBlurSamples;
+        private _floatTextureType;
+        private _ratio;
         private _bloomEnabled;
         private _depthOfFieldEnabled;
+        private _vlsEnabled;
         private _lensFlareEnabled;
         private _hdrEnabled;
         private _motionBlurEnabled;
+        private _motionBlurSamples;
+        private _volumetricLightStepsCount;
         BloomEnabled: boolean;
         DepthOfFieldEnabled: boolean;
         LensFlareEnabled: boolean;
         HDREnabled: boolean;
+        VLSEnabled: boolean;
         MotionBlurEnabled: boolean;
+        volumetricLightStepsCount: number;
         motionBlurSamples: number;
         /**
          * @constructor
@@ -17463,17 +17497,24 @@ declare module BABYLON {
          * @param {BABYLON.Camera[]} cameras - The array of cameras that the rendering pipeline will be attached to
          */
         constructor(name: string, scene: Scene, ratio: number, originalPostProcess?: PostProcess, cameras?: Camera[]);
+        private _buildPipeline();
         private _createDownSampleX4PostProcess(scene, ratio);
         private _createBrightPassPostProcess(scene, ratio);
-        private _createGaussianBlurPostProcesses(scene, ratio, indice, blurWidthKey?);
+        private _createBlurPostProcesses(scene, ratio, indice, blurWidthKey?);
         private _createTextureAdderPostProcess(scene, ratio);
+        private _createVolumetricLightPostProcess(scene, ratio);
         private _createLuminancePostProcesses(scene, textureType);
         private _createHdrPostProcess(scene, ratio);
         private _createLensFlarePostProcess(scene, ratio);
         private _createDepthOfFieldPostProcess(scene, ratio);
         private _createMotionBlurPostProcess(scene, ratio);
+        private _getDepthTexture();
+        private _disposePostProcesses();
         dispose(): void;
         serialize(): any;
+        /**
+         * Static members
+         */
         static Parse(source: any, scene: Scene, rootUrl: string): StandardRenderingPipeline;
         static LuminanceSteps: number;
     }

Різницю між файлами не показано, бо вона завелика
+ 41 - 82
dist/preview release/babylon.js


Різницю між файлами не показано, бо вона завелика
+ 601 - 286
dist/preview release/babylon.max.js


+ 256 - 215
dist/preview release/babylon.module.d.ts

@@ -241,6 +241,7 @@ declare module BABYLON {
         private _textureUnits;
         private _workingCanvas;
         private _workingContext;
+        private _dummyFramebuffer;
         private _externalData;
         private _bindedRenderFunction;
         private _vaoRecordInProgress;
@@ -570,6 +571,7 @@ declare module BABYLON {
         getFps(): number;
         getDeltaTime(): number;
         private _measureFps();
+        _readTexturePixels(texture: WebGLTexture, width: number, height: number, faceIndex?: number): Uint8Array;
         private _canRenderToFloatFramebuffer();
         private _canRenderToHalfFloatFramebuffer();
         private _canRenderToFramebuffer(type);
@@ -4023,120 +4025,6 @@ declare module BABYLON {
     }
 }
 
-declare module BABYLON {
-    class BoundingBox implements ICullable {
-        minimum: Vector3;
-        maximum: Vector3;
-        vectors: Vector3[];
-        center: Vector3;
-        centerWorld: Vector3;
-        extendSize: Vector3;
-        extendSizeWorld: Vector3;
-        directions: Vector3[];
-        vectorsWorld: Vector3[];
-        minimumWorld: Vector3;
-        maximumWorld: Vector3;
-        private _worldMatrix;
-        constructor(minimum: Vector3, maximum: Vector3);
-        getWorldMatrix(): Matrix;
-        setWorldMatrix(matrix: Matrix): BoundingBox;
-        _update(world: Matrix): void;
-        isInFrustum(frustumPlanes: Plane[]): boolean;
-        isCompletelyInFrustum(frustumPlanes: Plane[]): boolean;
-        intersectsPoint(point: Vector3): boolean;
-        intersectsSphere(sphere: BoundingSphere): boolean;
-        intersectsMinMax(min: Vector3, max: Vector3): boolean;
-        static Intersects(box0: BoundingBox, box1: BoundingBox): boolean;
-        static IntersectsSphere(minPoint: Vector3, maxPoint: Vector3, sphereCenter: Vector3, sphereRadius: number): boolean;
-        static IsCompletelyInFrustum(boundingVectors: Vector3[], frustumPlanes: Plane[]): boolean;
-        static IsInFrustum(boundingVectors: Vector3[], frustumPlanes: Plane[]): boolean;
-    }
-}
-
-declare module BABYLON {
-    interface ICullable {
-        isInFrustum(frustumPlanes: Plane[]): boolean;
-        isCompletelyInFrustum(frustumPlanes: Plane[]): boolean;
-    }
-    class BoundingInfo implements ICullable {
-        minimum: Vector3;
-        maximum: Vector3;
-        boundingBox: BoundingBox;
-        boundingSphere: BoundingSphere;
-        private _isLocked;
-        constructor(minimum: Vector3, maximum: Vector3);
-        isLocked: boolean;
-        update(world: Matrix): void;
-        isInFrustum(frustumPlanes: Plane[]): boolean;
-        isCompletelyInFrustum(frustumPlanes: Plane[]): boolean;
-        _checkCollision(collider: Collider): boolean;
-        intersectsPoint(point: Vector3): boolean;
-        intersects(boundingInfo: BoundingInfo, precise: boolean): boolean;
-    }
-}
-
-declare module BABYLON {
-    class BoundingSphere {
-        minimum: Vector3;
-        maximum: Vector3;
-        center: Vector3;
-        radius: number;
-        centerWorld: Vector3;
-        radiusWorld: number;
-        private _tempRadiusVector;
-        constructor(minimum: Vector3, maximum: Vector3);
-        _update(world: Matrix): void;
-        isInFrustum(frustumPlanes: Plane[]): boolean;
-        intersectsPoint(point: Vector3): boolean;
-        static Intersects(sphere0: BoundingSphere, sphere1: BoundingSphere): boolean;
-    }
-}
-
-declare module BABYLON {
-    class Ray {
-        origin: Vector3;
-        direction: Vector3;
-        length: number;
-        private _edge1;
-        private _edge2;
-        private _pvec;
-        private _tvec;
-        private _qvec;
-        private _tmpRay;
-        private _rayHelper;
-        constructor(origin: Vector3, direction: Vector3, length?: number);
-        intersectsBoxMinMax(minimum: Vector3, maximum: Vector3): boolean;
-        intersectsBox(box: BoundingBox): boolean;
-        intersectsSphere(sphere: BoundingSphere): boolean;
-        intersectsTriangle(vertex0: Vector3, vertex1: Vector3, vertex2: Vector3): IntersectionInfo;
-        intersectsPlane(plane: Plane): number;
-        intersectsMesh(mesh: AbstractMesh, fastCheck?: boolean): PickingInfo;
-        intersectsMeshes(meshes: Array<AbstractMesh>, fastCheck?: boolean, results?: Array<PickingInfo>): Array<PickingInfo>;
-        private _comparePickingInfo(pickingInfoA, pickingInfoB);
-        private static smallnum;
-        private static rayl;
-        /**
-         * Intersection test between the ray and a given segment whithin a given tolerance (threshold)
-         * @param sega the first point of the segment to test the intersection against
-         * @param segb the second point of the segment to test the intersection against
-         * @param threshold the tolerance margin, if the ray doesn't intersect the segment but is close to the given threshold, the intersection is successful
-         * @return the distance from the ray origin to the intersection point if there's intersection, or -1 if there's no intersection
-         */
-        intersectionSegment(sega: Vector3, segb: Vector3, threshold: number): number;
-        static CreateNew(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Ray;
-        /**
-        * Function will create a new transformed ray starting from origin and ending at the end point. Ray's length will be set, and ray will be
-        * transformed to the given world matrix.
-        * @param origin The origin point
-        * @param end The end point
-        * @param world a matrix to transform the ray to. Default is the identity matrix.
-        */
-        static CreateNewFromTo(origin: Vector3, end: Vector3, world?: Matrix): Ray;
-        static Transform(ray: Ray, matrix: Matrix): Ray;
-        static TransformToRef(ray: Ray, matrix: Matrix, result: Ray): void;
-    }
-}
-
 declare module BABYLON.Debug {
     class AxesViewer {
         private _xline;
@@ -4499,6 +4387,120 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    class BoundingBox implements ICullable {
+        minimum: Vector3;
+        maximum: Vector3;
+        vectors: Vector3[];
+        center: Vector3;
+        centerWorld: Vector3;
+        extendSize: Vector3;
+        extendSizeWorld: Vector3;
+        directions: Vector3[];
+        vectorsWorld: Vector3[];
+        minimumWorld: Vector3;
+        maximumWorld: Vector3;
+        private _worldMatrix;
+        constructor(minimum: Vector3, maximum: Vector3);
+        getWorldMatrix(): Matrix;
+        setWorldMatrix(matrix: Matrix): BoundingBox;
+        _update(world: Matrix): void;
+        isInFrustum(frustumPlanes: Plane[]): boolean;
+        isCompletelyInFrustum(frustumPlanes: Plane[]): boolean;
+        intersectsPoint(point: Vector3): boolean;
+        intersectsSphere(sphere: BoundingSphere): boolean;
+        intersectsMinMax(min: Vector3, max: Vector3): boolean;
+        static Intersects(box0: BoundingBox, box1: BoundingBox): boolean;
+        static IntersectsSphere(minPoint: Vector3, maxPoint: Vector3, sphereCenter: Vector3, sphereRadius: number): boolean;
+        static IsCompletelyInFrustum(boundingVectors: Vector3[], frustumPlanes: Plane[]): boolean;
+        static IsInFrustum(boundingVectors: Vector3[], frustumPlanes: Plane[]): boolean;
+    }
+}
+
+declare module BABYLON {
+    interface ICullable {
+        isInFrustum(frustumPlanes: Plane[]): boolean;
+        isCompletelyInFrustum(frustumPlanes: Plane[]): boolean;
+    }
+    class BoundingInfo implements ICullable {
+        minimum: Vector3;
+        maximum: Vector3;
+        boundingBox: BoundingBox;
+        boundingSphere: BoundingSphere;
+        private _isLocked;
+        constructor(minimum: Vector3, maximum: Vector3);
+        isLocked: boolean;
+        update(world: Matrix): void;
+        isInFrustum(frustumPlanes: Plane[]): boolean;
+        isCompletelyInFrustum(frustumPlanes: Plane[]): boolean;
+        _checkCollision(collider: Collider): boolean;
+        intersectsPoint(point: Vector3): boolean;
+        intersects(boundingInfo: BoundingInfo, precise: boolean): boolean;
+    }
+}
+
+declare module BABYLON {
+    class BoundingSphere {
+        minimum: Vector3;
+        maximum: Vector3;
+        center: Vector3;
+        radius: number;
+        centerWorld: Vector3;
+        radiusWorld: number;
+        private _tempRadiusVector;
+        constructor(minimum: Vector3, maximum: Vector3);
+        _update(world: Matrix): void;
+        isInFrustum(frustumPlanes: Plane[]): boolean;
+        intersectsPoint(point: Vector3): boolean;
+        static Intersects(sphere0: BoundingSphere, sphere1: BoundingSphere): boolean;
+    }
+}
+
+declare module BABYLON {
+    class Ray {
+        origin: Vector3;
+        direction: Vector3;
+        length: number;
+        private _edge1;
+        private _edge2;
+        private _pvec;
+        private _tvec;
+        private _qvec;
+        private _tmpRay;
+        private _rayHelper;
+        constructor(origin: Vector3, direction: Vector3, length?: number);
+        intersectsBoxMinMax(minimum: Vector3, maximum: Vector3): boolean;
+        intersectsBox(box: BoundingBox): boolean;
+        intersectsSphere(sphere: BoundingSphere): boolean;
+        intersectsTriangle(vertex0: Vector3, vertex1: Vector3, vertex2: Vector3): IntersectionInfo;
+        intersectsPlane(plane: Plane): number;
+        intersectsMesh(mesh: AbstractMesh, fastCheck?: boolean): PickingInfo;
+        intersectsMeshes(meshes: Array<AbstractMesh>, fastCheck?: boolean, results?: Array<PickingInfo>): Array<PickingInfo>;
+        private _comparePickingInfo(pickingInfoA, pickingInfoB);
+        private static smallnum;
+        private static rayl;
+        /**
+         * Intersection test between the ray and a given segment whithin a given tolerance (threshold)
+         * @param sega the first point of the segment to test the intersection against
+         * @param segb the second point of the segment to test the intersection against
+         * @param threshold the tolerance margin, if the ray doesn't intersect the segment but is close to the given threshold, the intersection is successful
+         * @return the distance from the ray origin to the intersection point if there's intersection, or -1 if there's no intersection
+         */
+        intersectionSegment(sega: Vector3, segb: Vector3, threshold: number): number;
+        static CreateNew(x: number, y: number, viewportWidth: number, viewportHeight: number, world: Matrix, view: Matrix, projection: Matrix): Ray;
+        /**
+        * Function will create a new transformed ray starting from origin and ending at the end point. Ray's length will be set, and ray will be
+        * transformed to the given world matrix.
+        * @param origin The origin point
+        * @param end The end point
+        * @param world a matrix to transform the ray to. Default is the identity matrix.
+        */
+        static CreateNewFromTo(origin: Vector3, end: Vector3, world?: Matrix): Ray;
+        static Transform(ray: Ray, matrix: Matrix): Ray;
+        static TransformToRef(ray: Ray, matrix: Matrix, result: Ray): void;
+    }
+}
+
+declare module BABYLON {
     class LensFlare {
         size: number;
         position: number;
@@ -5077,61 +5079,6 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
-    interface ISceneLoaderPluginExtensions {
-        [extension: string]: {
-            isBinary: boolean;
-        };
-    }
-    interface ISceneLoaderPlugin {
-        extensions: string | ISceneLoaderPluginExtensions;
-        importMesh: (meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => boolean;
-        load: (scene: Scene, data: string, rootUrl: string) => boolean;
-        canDirectLoad?: (data: string) => boolean;
-    }
-    interface ISceneLoaderPluginAsync {
-        extensions: string | ISceneLoaderPluginExtensions;
-        importMeshAsync: (meshesNames: any, scene: Scene, data: any, rootUrl: string, onsuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror: () => void) => void;
-        loadAsync: (scene: Scene, data: string, rootUrl: string, onsuccess: () => void, onerror: () => void) => void;
-        canDirectLoad?: (data: string) => boolean;
-    }
-    class SceneLoader {
-        private static _ForceFullSceneLoadingForIncremental;
-        private static _ShowLoadingScreen;
-        static readonly NO_LOGGING: number;
-        static readonly MINIMAL_LOGGING: number;
-        static readonly SUMMARY_LOGGING: number;
-        static readonly DETAILED_LOGGING: number;
-        private static _loggingLevel;
-        static ForceFullSceneLoadingForIncremental: boolean;
-        static ShowLoadingScreen: boolean;
-        static loggingLevel: number;
-        private static _registeredPlugins;
-        private static _getDefaultPlugin();
-        private static _getPluginForExtension(extension);
-        private static _getPluginForDirectLoad(data);
-        private static _getPluginForFilename(sceneFilename);
-        private static _getDirectLoad(sceneFilename);
-        static GetPluginForExtension(extension: string): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
-        static RegisterPlugin(plugin: ISceneLoaderPlugin | ISceneLoaderPluginAsync): void;
-        static ImportMesh(meshesNames: any, rootUrl: string, sceneFilename: string, scene: Scene, onsuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, progressCallBack?: () => void, onerror?: (scene: Scene, message: string, exception?: any) => void): void;
-        /**
-        * Load a scene
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
-        * @param engine is the instance of BABYLON.Engine to use to create the scene
-        */
-        static Load(rootUrl: string, sceneFilename: any, engine: Engine, onsuccess?: (scene: Scene) => void, progressCallBack?: any, onerror?: (scene: Scene) => void): void;
-        /**
-        * Append a scene
-        * @param rootUrl a string that defines the root url for scene and resources
-        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
-        * @param scene is the instance of BABYLON.Scene to append to
-        */
-        static Append(rootUrl: string, sceneFilename: any, scene: Scene, onsuccess?: (scene: Scene) => void, progressCallBack?: any, onerror?: (scene: Scene) => void): void;
-    }
-}
-
-declare module BABYLON {
     /**
      * The color grading curves provide additional color adjustmnent that is applied after any color grading transform (3D LUT).
      * They allow basic adjustment of saturation and small exposure adjustments, along with color filter tinting to provide white balance adjustment or more stylistic effects.
@@ -5626,9 +5573,12 @@ declare module BABYLON {
         bindViewProjection(effect: Effect): void;
         protected _afterBind(mesh: Mesh): void;
         unbind(): void;
+        getActiveTextures(): BaseTexture[];
         clone(name: string): Material;
         getBindedMeshes(): AbstractMesh[];
-        forceCompilation(mesh: AbstractMesh, onCompiled: (material: Material) => void): void;
+        forceCompilation(mesh: AbstractMesh, onCompiled: (material: Material) => void, options: {
+            alphaTest: boolean;
+        }): void;
         markAsDirty(flag: number): void;
         protected _markAllSubMeshesAsDirty(func: (defines: MaterialDefines) => void): void;
         protected _markAllSubMeshesAsTexturesDirty(): void;
@@ -5672,6 +5622,7 @@ declare module BABYLON {
         constructor(name: string, scene: Scene);
         private _hookArray(array);
         getSubMaterial(index: any): Material;
+        getActiveTextures(): BaseTexture[];
         getClassName(): string;
         isReady(mesh?: AbstractMesh): boolean;
         clone(name: string, cloneChildren?: boolean): MultiMaterial;
@@ -5733,6 +5684,7 @@ declare module BABYLON {
         isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean;
         bindOnlyWorldMatrix(world: Matrix): void;
         bind(world: Matrix, mesh?: Mesh): void;
+        getActiveTextures(): BaseTexture[];
         clone(name: string): ShaderMaterial;
         dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean): void;
         serialize(): any;
@@ -5921,6 +5873,7 @@ declare module BABYLON {
         unbind(): void;
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
+        getActiveTextures(): BaseTexture[];
         dispose(forceDisposeEffect?: boolean, forceDisposeTextures?: boolean): void;
         clone(name: string): StandardMaterial;
         serialize(): any;
@@ -8254,6 +8207,61 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    interface ISceneLoaderPluginExtensions {
+        [extension: string]: {
+            isBinary: boolean;
+        };
+    }
+    interface ISceneLoaderPlugin {
+        extensions: string | ISceneLoaderPluginExtensions;
+        importMesh: (meshesNames: any, scene: Scene, data: any, rootUrl: string, meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => boolean;
+        load: (scene: Scene, data: string, rootUrl: string) => boolean;
+        canDirectLoad?: (data: string) => boolean;
+    }
+    interface ISceneLoaderPluginAsync {
+        extensions: string | ISceneLoaderPluginExtensions;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: any, rootUrl: string, onsuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror: () => void) => void;
+        loadAsync: (scene: Scene, data: string, rootUrl: string, onsuccess: () => void, onerror: () => void) => void;
+        canDirectLoad?: (data: string) => boolean;
+    }
+    class SceneLoader {
+        private static _ForceFullSceneLoadingForIncremental;
+        private static _ShowLoadingScreen;
+        static readonly NO_LOGGING: number;
+        static readonly MINIMAL_LOGGING: number;
+        static readonly SUMMARY_LOGGING: number;
+        static readonly DETAILED_LOGGING: number;
+        private static _loggingLevel;
+        static ForceFullSceneLoadingForIncremental: boolean;
+        static ShowLoadingScreen: boolean;
+        static loggingLevel: number;
+        private static _registeredPlugins;
+        private static _getDefaultPlugin();
+        private static _getPluginForExtension(extension);
+        private static _getPluginForDirectLoad(data);
+        private static _getPluginForFilename(sceneFilename);
+        private static _getDirectLoad(sceneFilename);
+        static GetPluginForExtension(extension: string): ISceneLoaderPlugin | ISceneLoaderPluginAsync;
+        static RegisterPlugin(plugin: ISceneLoaderPlugin | ISceneLoaderPluginAsync): void;
+        static ImportMesh(meshesNames: any, rootUrl: string, sceneFilename: string, scene: Scene, onsuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, progressCallBack?: () => void, onerror?: (scene: Scene, message: string, exception?: any) => void): void;
+        /**
+        * Load a scene
+        * @param rootUrl a string that defines the root url for scene and resources
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param engine is the instance of BABYLON.Engine to use to create the scene
+        */
+        static Load(rootUrl: string, sceneFilename: any, engine: Engine, onsuccess?: (scene: Scene) => void, progressCallBack?: any, onerror?: (scene: Scene) => void): void;
+        /**
+        * Append a scene
+        * @param rootUrl a string that defines the root url for scene and resources
+        * @param sceneFilename a string that defines the name of the scene file. can start with "data:" following by the stringified version of the scene
+        * @param scene is the instance of BABYLON.Scene to append to
+        */
+        static Append(rootUrl: string, sceneFilename: any, scene: Scene, onsuccess?: (scene: Scene) => void, progressCallBack?: any, onerror?: (scene: Scene) => void): void;
+    }
+}
+
+declare module BABYLON {
     class AbstractMesh extends Node implements IDisposable, ICullable, IGetSetVerticesData {
         private static _BILLBOARDMODE_NONE;
         private static _BILLBOARDMODE_X;
@@ -12479,6 +12487,36 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
+    class ReflectionProbe {
+        name: string;
+        private _scene;
+        private _renderTargetTexture;
+        private _projectionMatrix;
+        private _viewMatrix;
+        private _target;
+        private _add;
+        private _attachedMesh;
+        invertYAxis: boolean;
+        position: Vector3;
+        constructor(name: string, size: number, scene: Scene, generateMipMaps?: boolean);
+        samples: number;
+        refreshRate: number;
+        getScene(): Scene;
+        readonly cubeTexture: RenderTargetTexture;
+        readonly renderList: AbstractMesh[];
+        attachToMesh(mesh: AbstractMesh): void;
+        /**
+         * Specifies whether or not the stencil and depth buffer are cleared between two rendering groups.
+         *
+         * @param renderingGroupId The rendering group id corresponding to its index
+         * @param autoClearDepthStencil Automatically clears depth and stencil between groups if true.
+         */
+        setRenderingAutoClearDepthStencil(renderingGroupId: number, autoClearDepthStencil: boolean): void;
+        dispose(): void;
+    }
+}
+
+declare module BABYLON {
     class AnaglyphPostProcess extends PostProcess {
         private _passedProcess;
         constructor(name: string, options: number | PostProcessOptions, rigCameras: Camera[], samplingMode?: number, engine?: Engine, reusable?: boolean);
@@ -12884,36 +12922,6 @@ declare module BABYLON {
 }
 
 declare module BABYLON {
-    class ReflectionProbe {
-        name: string;
-        private _scene;
-        private _renderTargetTexture;
-        private _projectionMatrix;
-        private _viewMatrix;
-        private _target;
-        private _add;
-        private _attachedMesh;
-        invertYAxis: boolean;
-        position: Vector3;
-        constructor(name: string, size: number, scene: Scene, generateMipMaps?: boolean);
-        samples: number;
-        refreshRate: number;
-        getScene(): Scene;
-        readonly cubeTexture: RenderTargetTexture;
-        readonly renderList: AbstractMesh[];
-        attachToMesh(mesh: AbstractMesh): void;
-        /**
-         * Specifies whether or not the stencil and depth buffer are cleared between two rendering groups.
-         *
-         * @param renderingGroupId The rendering group id corresponding to its index
-         * @param autoClearDepthStencil Automatically clears depth and stencil between groups if true.
-         */
-        setRenderingAutoClearDepthStencil(renderingGroupId: number, autoClearDepthStencil: boolean): void;
-        dispose(): void;
-    }
-}
-
-declare module BABYLON {
     class BoundingBoxRenderer {
         frontColor: Color3;
         backColor: Color3;
@@ -12978,17 +12986,21 @@ declare module BABYLON {
         private _scene;
         private _multiRenderTarget;
         private _effect;
+        private _ratio;
         private _viewMatrix;
         private _projectionMatrix;
         private _transformMatrix;
         private _worldViewProjection;
         private _cachedDefines;
+        private _enablePosition;
         renderList: Mesh[];
         readonly isSupported: boolean;
+        enablePosition: boolean;
         constructor(scene: Scene, ratio?: number);
         isReady(subMesh: SubMesh, useInstances: boolean): boolean;
         getGBuffer(): MultiRenderTarget;
         dispose(): void;
+        private _createRenderTargets();
     }
 }
 
@@ -15229,9 +15241,6 @@ declare module BABYLON {
     }
 }
 
-declare module BABYLON.Internals {
-}
-
 declare module BABYLON {
     /**
      * The Physically based material base class of BJS.
@@ -15240,7 +15249,7 @@ declare module BABYLON {
      * For more information, please refer to the documentation :
      * http://doc.babylonjs.com/extensions/Physically_Based_Rendering
      */
-    abstract class PBRBaseMaterial extends BABYLON.PushMaterial {
+    abstract class PBRBaseMaterial extends PushMaterial {
         /**
          * Intensity of the direct lights e.g. the four lights available in your scene.
          * This impacts both the direct diffuse and specular highlights.
@@ -15840,6 +15849,7 @@ declare module BABYLON {
          */
         constructor(name: string, scene: Scene);
         getClassName(): string;
+        getActiveTextures(): BaseTexture[];
         clone(name: string): PBRMaterial;
         serialize(): any;
         static Parse(source: any, scene: Scene, rootUrl: string): PBRMaterial;
@@ -15893,6 +15903,10 @@ declare module BABYLON {
          */
         getClassName(): string;
         /**
+         * Return the active textures of the material.
+         */
+        getActiveTextures(): BaseTexture[];
+        /**
          * Serialize the material to a parsable JSON object.
          */
         serialize(): any;
@@ -15944,6 +15958,10 @@ declare module BABYLON {
          */
         getClassName(): string;
         /**
+         * Return the active textures of the material.
+         */
+        getActiveTextures(): BaseTexture[];
+        /**
          * Serialize the material to a parsable JSON object.
          */
         serialize(): any;
@@ -16001,9 +16019,11 @@ declare module BABYLON {
         _getFromCache(url: string, noMipmap: boolean, sampling?: number): WebGLTexture;
         delayLoad(): void;
         clone(): BaseTexture;
+        readPixels(faceIndex?: number): Uint8Array;
         releaseInternalTexture(): void;
         dispose(): void;
         serialize(): any;
+        static WhenAllReady(textures: BaseTexture[], onLoad: () => void): void;
     }
 }
 
@@ -16510,7 +16530,7 @@ declare module BABYLON {
         protected _format: number;
         private _delayedOnLoad;
         private _delayedOnError;
-        private _onLoadObservarble;
+        private _onLoadObservable;
         protected _isBlocking: boolean;
         isBlocking: boolean;
         constructor(url: string, scene: Scene, noMipmap?: boolean, invertY?: boolean, samplingMode?: number, onLoad?: () => void, onError?: () => void, buffer?: any, deleteBuffer?: boolean, format?: number);
@@ -16521,7 +16541,7 @@ declare module BABYLON {
         getTextureMatrix(): Matrix;
         getReflectionTextureMatrix(): Matrix;
         clone(): Texture;
-        readonly onLoadObservable: Observable<boolean>;
+        readonly onLoadObservable: Observable<Texture>;
         static CreateFromBase64String(data: string, name: string, scene: Scene, noMipmap?: boolean, invertY?: boolean, samplingMode?: number, onLoad?: () => void, onError?: () => void, format?: number): Texture;
         static Parse(parsedTexture: any, scene: Scene, rootUrl: string): BaseTexture;
         static LoadFromDataString(name: string, buffer: any, scene: Scene, deleteBuffer?: boolean, noMipmap?: boolean, invertY?: boolean, samplingMode?: number, onLoad?: () => void, onError?: () => void, format?: number): Texture;
@@ -16559,6 +16579,9 @@ declare module BABYLON {
     }
 }
 
+declare module BABYLON.Internals {
+}
+
 declare module BABYLON {
     class CannonJSPlugin implements IPhysicsEnginePlugin {
         private _useDeltaForWorldStep;
@@ -17399,9 +17422,14 @@ declare module BABYLON {
         originalPostProcess: PostProcess;
         downSampleX4PostProcess: PostProcess;
         brightPassPostProcess: PostProcess;
-        gaussianBlurHPostProcesses: PostProcess[];
-        gaussianBlurVPostProcesses: PostProcess[];
+        blurHPostProcesses: PostProcess[];
+        blurVPostProcesses: PostProcess[];
         textureAdderPostProcess: PostProcess;
+        volumetricLightPostProcess: PostProcess;
+        volumetricLightSmoothXPostProcess: BlurPostProcess;
+        volumetricLightSmoothYPostProcess: BlurPostProcess;
+        volumetricLightMergePostProces: PostProcess;
+        volumetricLightFinalPostProcess: PostProcess;
         luminancePostProcess: PostProcess;
         luminanceDownSamplePostProcesses: PostProcess[];
         hdrPostProcess: PostProcess;
@@ -17415,11 +17443,12 @@ declare module BABYLON {
         brightThreshold: number;
         blurWidth: number;
         horizontalBlur: boolean;
-        gaussianCoefficient: number;
-        gaussianMean: number;
-        gaussianStandardDeviation: number;
         exposure: number;
         lensTexture: Texture;
+        volumetricLightCoefficient: number;
+        volumetricLightPower: number;
+        volumetricLightBlurScale: number;
+        sourceLight: SpotLight | DirectionalLight;
         hdrMinimumLuminance: number;
         hdrDecreaseRate: number;
         hdrIncreaseRate: number;
@@ -17438,21 +17467,26 @@ declare module BABYLON {
         * Private members
         */
         private _scene;
-        private _depthRenderer;
         private _currentDepthOfFieldSource;
-        private _currentHDRSource;
+        private _basePostProcess;
         private _hdrCurrentLuminance;
-        private _motionBlurSamples;
+        private _floatTextureType;
+        private _ratio;
         private _bloomEnabled;
         private _depthOfFieldEnabled;
+        private _vlsEnabled;
         private _lensFlareEnabled;
         private _hdrEnabled;
         private _motionBlurEnabled;
+        private _motionBlurSamples;
+        private _volumetricLightStepsCount;
         BloomEnabled: boolean;
         DepthOfFieldEnabled: boolean;
         LensFlareEnabled: boolean;
         HDREnabled: boolean;
+        VLSEnabled: boolean;
         MotionBlurEnabled: boolean;
+        volumetricLightStepsCount: number;
         motionBlurSamples: number;
         /**
          * @constructor
@@ -17463,17 +17497,24 @@ declare module BABYLON {
          * @param {BABYLON.Camera[]} cameras - The array of cameras that the rendering pipeline will be attached to
          */
         constructor(name: string, scene: Scene, ratio: number, originalPostProcess?: PostProcess, cameras?: Camera[]);
+        private _buildPipeline();
         private _createDownSampleX4PostProcess(scene, ratio);
         private _createBrightPassPostProcess(scene, ratio);
-        private _createGaussianBlurPostProcesses(scene, ratio, indice, blurWidthKey?);
+        private _createBlurPostProcesses(scene, ratio, indice, blurWidthKey?);
         private _createTextureAdderPostProcess(scene, ratio);
+        private _createVolumetricLightPostProcess(scene, ratio);
         private _createLuminancePostProcesses(scene, textureType);
         private _createHdrPostProcess(scene, ratio);
         private _createLensFlarePostProcess(scene, ratio);
         private _createDepthOfFieldPostProcess(scene, ratio);
         private _createMotionBlurPostProcess(scene, ratio);
+        private _getDepthTexture();
+        private _disposePostProcesses();
         dispose(): void;
         serialize(): any;
+        /**
+         * Static members
+         */
         static Parse(source: any, scene: Scene, rootUrl: string): StandardRenderingPipeline;
         static LuminanceSteps: number;
     }

Різницю між файлами не показано, бо вона завелика
+ 40 - 82
dist/preview release/babylon.worker.js


Різницю між файлами не показано, бо вона завелика
+ 794 - 758
dist/preview release/customConfigurations/minimalViewer/babylon.d.ts


Різницю між файлами не показано, бо вона завелика
+ 20 - 20
dist/preview release/customConfigurations/minimalViewer/babylon.js


Різницю між файлами не показано, бо вона завелика
+ 157 - 15
dist/preview release/customConfigurations/minimalViewer/babylon.max.js


Різницю між файлами не показано, бо вона завелика
+ 794 - 758
dist/preview release/customConfigurations/minimalViewer/babylon.module.d.ts


Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/gui/babylon.gui.min.js


Різницю між файлами не показано, бо вона завелика
+ 263 - 263
dist/preview release/inspector/babylon.inspector.bundle.js


+ 30 - 1
dist/preview release/inspector/babylon.inspector.d.ts

@@ -65,7 +65,7 @@ declare module INSPECTOR {
 }
 
 declare module INSPECTOR {
-    const PROPERTIES: {
+    var PROPERTIES: {
         format: (obj: any) => any;
         'type_not_defined': {
             properties: any[];
@@ -260,6 +260,13 @@ declare module INSPECTOR {
 
 declare module INSPECTOR {
     /**
+     * Function that add gui objects properties to the variable PROPERTIES
+     */
+    function loadGUIProperties(): void;
+}
+
+declare module INSPECTOR {
+    /**
      * Represents a html div element.
      * The div is built when an instance of BasicElement is created.
      */
@@ -326,6 +333,21 @@ declare module INSPECTOR {
 }
 
 declare module INSPECTOR {
+    class GUIAdapter extends Adapter implements IToolVisible {
+        constructor(obj: BABYLON.GUI.Control);
+        /** Returns the name displayed in the tree */
+        id(): string;
+        /** Returns the type of this object - displayed in the tree */
+        type(): string;
+        /** Returns the list of properties to be displayed for this adapter */
+        getProperties(): Array<PropertyLine>;
+        getTools(): Array<AbstractTreeTool>;
+        setVisible(b: boolean): void;
+        isVisible(): boolean;
+    }
+}
+
+declare module INSPECTOR {
     class SoundAdapter extends Adapter implements ISoundInteractions {
         constructor(obj: BABYLON.Sound);
         /** Returns the name displayed in the tree */
@@ -805,6 +827,13 @@ declare module INSPECTOR {
 }
 
 declare module INSPECTOR {
+    class GUITab extends PropertyTab {
+        constructor(tabbar: TabBar, inspector: Inspector);
+        protected _getTree(): Array<TreeItem>;
+    }
+}
+
+declare module INSPECTOR {
     class SoundTab extends PropertyTab {
         constructor(tabbar: TabBar, inspector: Inspector);
         protected _getTree(): Array<TreeItem>;

+ 318 - 4
dist/preview release/inspector/babylon.inspector.js

@@ -9,6 +9,8 @@ var INSPECTOR;
             var _this = this;
             /** True if the inspector is built as a popup tab */
             this._popupMode = false;
+            //Load properties of GUI objects now as BABYLON.GUI has to be declared before 
+            INSPECTOR.loadGUIProperties();
             //get Tabbar initialTab
             this._initialTab = initialTab;
             //get parentElement of our Inspector
@@ -710,6 +712,125 @@ var INSPECTOR;
 var INSPECTOR;
 (function (INSPECTOR) {
     /**
+     * Function that add gui objects properties to the variable PROPERTIES
+     */
+    function loadGUIProperties() {
+        var PROPERTIES_GUI = {
+            'ValueAndUnit': {
+                type: BABYLON.GUI.ValueAndUnit,
+                properties: ['_value', 'unit'],
+                format: function (valueAndUnit) { return valueAndUnit; }
+            },
+            'Control': {
+                type: BABYLON.GUI.Control,
+                properties: [
+                    '_alpha',
+                    '_fontFamily',
+                    '_color',
+                    '_scaleX',
+                    '_scaleY',
+                    '_rotation',
+                    '_currentMeasure',
+                    '_width',
+                    '_height',
+                    '_left',
+                    '_top',
+                    '_linkedMesh',
+                    'isHitTestVisible',
+                    'isPointerBlocker',
+                ],
+                format: function (control) { return control.name; }
+            },
+            'Button': {
+                type: BABYLON.GUI.Button,
+                properties: [],
+                format: function (button) { return button.name; }
+            },
+            'ColorPicker': {
+                type: BABYLON.GUI.ColorPicker,
+                properties: ['_value'],
+                format: function (colorPicker) { return colorPicker.name; }
+            },
+            'Checkbox': {
+                type: BABYLON.GUI.Checkbox,
+                properties: ['_isChecked', '_background'],
+                format: function (checkbox) { return checkbox.name; }
+            },
+            'Ellipse': {
+                type: BABYLON.GUI.Ellipse,
+                properties: ['_thickness'],
+                format: function (ellipse) { return ellipse.name; }
+            },
+            'Image': {
+                type: BABYLON.GUI.Image,
+                properties: [
+                    '_imageWidth',
+                    '_imageHeight',
+                    '_loaded',
+                    '_source',
+                ],
+                format: function (image) { return image.name; }
+            },
+            'Line': {
+                type: BABYLON.GUI.Line,
+                properties: ['_lineWidth',
+                    '_background',
+                    '_x1',
+                    '_y1',
+                    '_x2',
+                    '_y2',
+                ],
+                format: function (line) { return line.name; }
+            },
+            'RadioButton': {
+                type: BABYLON.GUI.RadioButton,
+                properties: ['_isChecked', '_background'],
+                format: function (radioButton) { return radioButton.name; }
+            },
+            'Rectangle': {
+                type: BABYLON.GUI.Rectangle,
+                properties: ['_thickness', '_cornerRadius'],
+                format: function (rectangle) { return rectangle.name; }
+            },
+            'Slider': {
+                type: BABYLON.GUI.Slider,
+                properties: [
+                    '_minimum',
+                    '_maximum',
+                    '_value',
+                    '_background',
+                    '_borderColor',
+                ],
+                format: function (slider) { return slider.name; }
+            },
+            'StackPanel': {
+                type: BABYLON.GUI.StackPanel,
+                properties: ['_isVertical'],
+                format: function (stackPanel) { return stackPanel.name; }
+            },
+            'TextBlock': {
+                type: BABYLON.GUI.TextBlock,
+                properties: ['_text', '_textWrapping'],
+                format: function (textBlock) { return textBlock.name; }
+            },
+            'Container': {
+                type: BABYLON.GUI.Container,
+                properties: ['_background'],
+                format: function (container) { return container.name; }
+            },
+        };
+        for (var prop in PROPERTIES_GUI) {
+            INSPECTOR.PROPERTIES[prop] = PROPERTIES_GUI[prop];
+        }
+    }
+    INSPECTOR.loadGUIProperties = loadGUIProperties;
+})(INSPECTOR || (INSPECTOR = {}));
+
+//# sourceMappingURL=properties_gui.js.map
+
+var INSPECTOR;
+(function (INSPECTOR) {
+    /**
      * Represents a html div element.
      * The div is built when an instance of BasicElement is created.
      */
@@ -861,6 +982,147 @@ var __extends = (this && this.__extends) || (function () {
 })();
 var INSPECTOR;
 (function (INSPECTOR) {
+    var GUIAdapter = (function (_super) {
+        __extends(GUIAdapter, _super);
+        function GUIAdapter(obj) {
+            return _super.call(this, obj) || this;
+        }
+        /** Returns the name displayed in the tree */
+        GUIAdapter.prototype.id = function () {
+            var str = '';
+            if (this._obj.name) {
+                str = this._obj.name;
+            } // otherwise nothing displayed        
+            return str;
+        };
+        /** Returns the type of this object - displayed in the tree */
+        GUIAdapter.prototype.type = function () {
+            return INSPECTOR.Helpers.GET_TYPE(this._obj);
+        };
+        /** Returns the list of properties to be displayed for this adapter */
+        GUIAdapter.prototype.getProperties = function () {
+            var propertiesLines = [];
+            for (var _i = 0, _a = INSPECTOR.PROPERTIES['Control'].properties; _i < _a.length; _i++) {
+                var dirty = _a[_i];
+                var infos = new INSPECTOR.Property(dirty, this._obj);
+                propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+            }
+            if (this._obj instanceof BABYLON.GUI.Button) {
+                for (var _b = 0, _c = INSPECTOR.PROPERTIES['Button'].properties; _b < _c.length; _b++) {
+                    var dirty = _c[_b];
+                    var infos = new INSPECTOR.Property(dirty, this._obj);
+                    propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+                }
+            }
+            if (this._obj instanceof BABYLON.GUI.ColorPicker) {
+                for (var _d = 0, _e = INSPECTOR.PROPERTIES['ColorPicker'].properties; _d < _e.length; _d++) {
+                    var dirty = _e[_d];
+                    var infos = new INSPECTOR.Property(dirty, this._obj);
+                    propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+                }
+            }
+            if (this._obj instanceof BABYLON.GUI.Checkbox) {
+                for (var _f = 0, _g = INSPECTOR.PROPERTIES['Checkbox'].properties; _f < _g.length; _f++) {
+                    var dirty = _g[_f];
+                    var infos = new INSPECTOR.Property(dirty, this._obj);
+                    propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+                }
+            }
+            if (this._obj instanceof BABYLON.GUI.Ellipse) {
+                for (var _h = 0, _j = INSPECTOR.PROPERTIES['Ellipse'].properties; _h < _j.length; _h++) {
+                    var dirty = _j[_h];
+                    var infos = new INSPECTOR.Property(dirty, this._obj);
+                    propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+                }
+            }
+            if (this._obj instanceof BABYLON.GUI.Image) {
+                for (var _k = 0, _l = INSPECTOR.PROPERTIES['Image'].properties; _k < _l.length; _k++) {
+                    var dirty = _l[_k];
+                    var infos = new INSPECTOR.Property(dirty, this._obj);
+                    propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+                }
+            }
+            if (this._obj instanceof BABYLON.GUI.Line) {
+                for (var _m = 0, _o = INSPECTOR.PROPERTIES['Line'].properties; _m < _o.length; _m++) {
+                    var dirty = _o[_m];
+                    var infos = new INSPECTOR.Property(dirty, this._obj);
+                    propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+                }
+            }
+            if (this._obj instanceof BABYLON.GUI.RadioButton) {
+                for (var _p = 0, _q = INSPECTOR.PROPERTIES['RadioButton'].properties; _p < _q.length; _p++) {
+                    var dirty = _q[_p];
+                    var infos = new INSPECTOR.Property(dirty, this._obj);
+                    propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+                }
+            }
+            if (this._obj instanceof BABYLON.GUI.Rectangle) {
+                for (var _r = 0, _s = INSPECTOR.PROPERTIES['Rectangle'].properties; _r < _s.length; _r++) {
+                    var dirty = _s[_r];
+                    var infos = new INSPECTOR.Property(dirty, this._obj);
+                    propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+                }
+            }
+            if (this._obj instanceof BABYLON.GUI.Slider) {
+                for (var _t = 0, _u = INSPECTOR.PROPERTIES['Slider'].properties; _t < _u.length; _t++) {
+                    var dirty = _u[_t];
+                    var infos = new INSPECTOR.Property(dirty, this._obj);
+                    propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+                }
+            }
+            if (this._obj instanceof BABYLON.GUI.StackPanel) {
+                for (var _v = 0, _w = INSPECTOR.PROPERTIES['StackPanel'].properties; _v < _w.length; _v++) {
+                    var dirty = _w[_v];
+                    var infos = new INSPECTOR.Property(dirty, this._obj);
+                    propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+                }
+            }
+            if (this._obj instanceof BABYLON.GUI.TextBlock) {
+                for (var _x = 0, _y = INSPECTOR.PROPERTIES['TextBlock'].properties; _x < _y.length; _x++) {
+                    var dirty = _y[_x];
+                    var infos = new INSPECTOR.Property(dirty, this._obj);
+                    propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+                }
+            }
+            if (this._obj instanceof BABYLON.GUI.Container) {
+                for (var _z = 0, _0 = INSPECTOR.PROPERTIES['Container'].properties; _z < _0.length; _z++) {
+                    var dirty = _0[_z];
+                    var infos = new INSPECTOR.Property(dirty, this._obj);
+                    propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+                }
+            }
+            return propertiesLines;
+        };
+        GUIAdapter.prototype.getTools = function () {
+            var tools = [];
+            tools.push(new INSPECTOR.Checkbox(this));
+            return tools;
+        };
+        GUIAdapter.prototype.setVisible = function (b) {
+            this._obj.isVisible = b;
+        };
+        GUIAdapter.prototype.isVisible = function () {
+            return this._obj.isVisible;
+        };
+        return GUIAdapter;
+    }(INSPECTOR.Adapter));
+    INSPECTOR.GUIAdapter = GUIAdapter;
+})(INSPECTOR || (INSPECTOR = {}));
+
+//# sourceMappingURL=GUIAdapter.js.map
+
+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 INSPECTOR;
+(function (INSPECTOR) {
     var SoundAdapter = (function (_super) {
         __extends(SoundAdapter, _super);
         function SoundAdapter(obj) {
@@ -1952,8 +2214,6 @@ var INSPECTOR;
     INSPECTOR.CubeTextureElement = CubeTextureElement;
 })(INSPECTOR || (INSPECTOR = {}));
 
-//# sourceMappingURL=CubeTextureElement.js.map
-
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = Object.setPrototypeOf ||
         ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
@@ -1998,8 +2258,6 @@ var INSPECTOR;
     INSPECTOR.HDRCubeTextureElement = HDRCubeTextureElement;
 })(INSPECTOR || (INSPECTOR = {}));
 
-//# sourceMappingURL=HDRCubeTextureElement.js.map
-
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = Object.setPrototypeOf ||
         ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
@@ -2581,6 +2839,61 @@ var __extends = (this && this.__extends) || (function () {
 })();
 var INSPECTOR;
 (function (INSPECTOR) {
+    var GUITab = (function (_super) {
+        __extends(GUITab, _super);
+        function GUITab(tabbar, inspector) {
+            return _super.call(this, tabbar, 'GUI', inspector) || this;
+        }
+        /* Overrides super */
+        GUITab.prototype._getTree = function () {
+            var _this = this;
+            var arr = [];
+            // Recursive method building the tree panel
+            var createNode = function (obj) {
+                var descendants = obj.children;
+                if (descendants && descendants.length > 0) {
+                    var node = new INSPECTOR.TreeItem(_this, new INSPECTOR.GUIAdapter(obj));
+                    for (var _i = 0, descendants_1 = descendants; _i < descendants_1.length; _i++) {
+                        var child = descendants_1[_i];
+                        var n = createNode(child);
+                        node.add(n);
+                    }
+                    node.update();
+                    return node;
+                }
+                else {
+                    return new INSPECTOR.TreeItem(_this, new INSPECTOR.GUIAdapter(obj));
+                }
+            };
+            // get all textures from the first scene
+            var instances = this._inspector.scene;
+            for (var _i = 0, _a = instances.textures; _i < _a.length; _i++) {
+                var tex = _a[_i];
+                //only get GUI's textures
+                if (tex instanceof BABYLON.GUI.AdvancedDynamicTexture) {
+                    var node = createNode(tex._rootContainer);
+                    arr.push(node);
+                }
+            }
+            return arr;
+        };
+        return GUITab;
+    }(INSPECTOR.PropertyTab));
+    INSPECTOR.GUITab = GUITab;
+})(INSPECTOR || (INSPECTOR = {}));
+
+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 INSPECTOR;
+(function (INSPECTOR) {
     var SoundTab = (function (_super) {
         __extends(SoundTab, _super);
         function SoundTab(tabbar, inspector) {
@@ -3626,6 +3939,7 @@ var INSPECTOR;
             _this._tabs.push(new INSPECTOR.ShaderTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.LightTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.MaterialTab(_this, _this._inspector));
+            _this._tabs.push(new INSPECTOR.GUITab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.CameraTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.SoundTab(_this, _this._inspector));
             _this._toolBar = new INSPECTOR.Toolbar(_this._inspector);

Різницю між файлами не показано, бо вона завелика
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


Різницю між файлами не показано, бо вона завелика
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 42 - 30
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -120,15 +120,11 @@ declare module BABYLON.GLTF2 {
         samplers: IGLTFAnimationSampler[];
         targets?: any[];
     }
-    interface IGLTFAssetProfile extends IGLTFProperty {
-        api?: string;
-        version?: string;
-    }
     interface IGLTFAsset extends IGLTFChildRootProperty {
         copyright?: string;
         generator?: string;
-        profile?: IGLTFAssetProfile;
         version: string;
+        minVersion?: string;
     }
     interface IGLTFBuffer extends IGLTFChildRootProperty {
         uri?: string;
@@ -186,6 +182,7 @@ declare module BABYLON.GLTF2 {
         alphaMode?: string;
         alphaCutoff: number;
         doubleSided?: boolean;
+        index?: number;
         babylonMaterial?: PBRMaterial;
     }
     interface IGLTFMeshPrimitive extends IGLTFProperty {
@@ -214,6 +211,7 @@ declare module BABYLON.GLTF2 {
         translation?: number[];
         weights?: number[];
         index?: number;
+        parent?: IGLTFNode;
         babylonMesh?: Mesh;
         babylonSkinToBones?: {
             [skin: number]: Bone;
@@ -272,24 +270,26 @@ declare module BABYLON.GLTF2 {
 declare module BABYLON.GLTF2 {
     class GLTFLoader implements IGLTFLoader {
         private _gltf;
-        private _pendingCount;
-        private _onLoaded;
         private _errors;
         private _babylonScene;
         private _rootUrl;
         private _defaultMaterial;
+        private _onSuccess;
+        private _onError;
+        private _renderReady;
+        private _renderPendingCount;
+        private _loaderPendingCount;
         static Extensions: {
             [name: string]: GLTFLoaderExtension;
         };
         static RegisterExtension(extension: GLTFLoaderExtension): void;
-        static LoadMaterial(index: number): IGLTFMaterial;
-        static LoadCoreMaterial(index: number): Material;
-        static LoadCommonMaterialProperties(material: IGLTFMaterial): void;
-        static LoadAlphaProperties(material: IGLTFMaterial): void;
-        static LoadTexture(textureInfo: IGLTFTextureInfo): Texture;
+        readonly gltf: IGLTF;
+        readonly babylonScene: Scene;
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void): void;
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void): void;
         private _loadAsync(nodeNames, scene, data, rootUrl, onSuccess, onError);
+        private _onRenderReady();
+        private _onLoaderComplete();
         private _loadData(data);
         private _showMeshes();
         private _startAnimations();
@@ -298,27 +298,30 @@ declare module BABYLON.GLTF2 {
         private _loadSkin(node);
         private _updateBone(node, parentNode, skin, inverseBindMatrixData);
         private _createBone(node, skin);
-        private _loadMesh(node, parentNode);
+        private _loadMesh(node);
         private _loadMeshData(node, mesh, babylonMesh);
         private _loadVertexDataAsync(primitive, onSuccess);
         private _createMorphTargets(node, mesh, primitive, babylonMesh);
         private _loadMorphTargetsData(mesh, primitive, vertexData, babylonMesh);
         private _loadTransform(node, babylonMesh);
-        private _traverseScene(nodeNames, scene, action);
-        private _traverseNode(nodeNames, index, action, parentNode?);
+        private _traverseNodes(indices, action, parentNode?);
+        private _traverseNode(index, action, parentNode?);
         private _loadAnimations();
         private _loadAnimationChannel(animation, animationIndex, channelIndex);
         private _loadBufferAsync(index, onSuccess);
         private _loadBufferViewAsync(bufferView, byteOffset, byteLength, componentType, onSuccess);
         private _loadAccessorAsync(accessor, onSuccess);
-        private _addPendingData(data);
-        private _removePendingData(data);
+        addPendingData(data: any): void;
+        removePendingData(data: any): void;
+        addLoaderPendingData(data: any): void;
+        removeLoaderPendingData(data: any): void;
         private _getDefaultMaterial();
-        private _loadMaterial(index);
-        private _loadCoreMaterial(index);
-        private _loadCommonMaterialProperties(material);
-        private _loadAlphaProperties(material);
-        private _loadTexture(textureInfo);
+        private _loadMaterialMetallicRoughnessProperties(material);
+        loadMaterial(index: number, assign: (material: Material) => void): void;
+        createPbrMaterial(material: IGLTFMaterial): void;
+        loadMaterialBaseProperties(material: IGLTFMaterial): void;
+        loadMaterialAlphaProperties(material: IGLTFMaterial): void;
+        loadTexture(textureInfo: IGLTFTextureInfo): Texture;
     }
 }
 
@@ -364,19 +367,28 @@ declare module BABYLON.GLTF2 {
 
 declare module BABYLON.GLTF2 {
     abstract class GLTFLoaderExtension {
-        private _name;
         enabled: boolean;
-        constructor(name: string);
+        readonly abstract name: string;
+        protected loadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean;
+        static _Extensions: GLTFLoaderExtension[];
+        static LoadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean;
+        private static _ApplyExtensions(action);
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    class MSFTLOD extends GLTFLoaderExtension {
         readonly name: string;
-        protected loadMaterial(index: number): Material;
-        static LoadMaterial(index: number): Material;
+        protected loadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean;
+        private loadMaterialLOD(loader, material, materialLODs, lod, assign);
     }
 }
 
 
-declare module BABYLON.GLTF2 {
-    class GLTFMaterialsPbrSpecularGlossinessExtension extends GLTFLoaderExtension {
-        constructor();
-        protected loadMaterial(index: number): Material;
+declare module BABYLON.GLTF2.Extensions {
+    class KHRMaterialsPbrSpecularGlossiness extends GLTFLoaderExtension {
+        readonly name: string;
+        protected loadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean;
     }
 }

+ 319 - 200
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -295,23 +295,24 @@ var BABYLON;
                     BABYLON.Tools.Error("Extension with the same name '" + extension.name + "' already exists");
                     return;
                 }
-                this.Extensions[extension.name] = extension;
-            };
-            GLTFLoader.LoadMaterial = function (index) {
-                return BABYLON.GLTFFileLoader.GLTFLoaderV2._loadMaterial(index);
-            };
-            GLTFLoader.LoadCoreMaterial = function (index) {
-                return BABYLON.GLTFFileLoader.GLTFLoaderV2._loadCoreMaterial(index);
-            };
-            GLTFLoader.LoadCommonMaterialProperties = function (material) {
-                return BABYLON.GLTFFileLoader.GLTFLoaderV2._loadCommonMaterialProperties(material);
-            };
-            GLTFLoader.LoadAlphaProperties = function (material) {
-                return BABYLON.GLTFFileLoader.GLTFLoaderV2._loadAlphaProperties(material);
-            };
-            GLTFLoader.LoadTexture = function (textureInfo) {
-                return BABYLON.GLTFFileLoader.GLTFLoaderV2._loadTexture(textureInfo);
+                GLTFLoader.Extensions[extension.name] = extension;
+                // Keep the order of registration so that extensions registered first are called first.
+                GLTF2.GLTFLoaderExtension._Extensions.push(extension);
             };
+            Object.defineProperty(GLTFLoader.prototype, "gltf", {
+                get: function () {
+                    return this._gltf;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(GLTFLoader.prototype, "babylonScene", {
+                get: function () {
+                    return this._babylonScene;
+                },
+                enumerable: true,
+                configurable: true
+            });
             GLTFLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onSuccess, onError) {
                 var _this = this;
                 this._loadAsync(meshesNames, scene, data, rootUrl, function () {
@@ -340,28 +341,34 @@ var BABYLON;
                 this._loadAsync(null, scene, data, rootUrl, onSuccess, onError);
             };
             GLTFLoader.prototype._loadAsync = function (nodeNames, scene, data, rootUrl, onSuccess, onError) {
-                var _this = this;
                 scene.useRightHandedSystem = true;
                 this._clear();
                 this._loadData(data);
                 this._babylonScene = scene;
                 this._rootUrl = rootUrl;
-                this._onLoaded = function () {
-                    _this._showMeshes();
-                    _this._startAnimations();
-                    if (_this._errors.length === 0) {
-                        onSuccess();
-                    }
-                    else {
-                        _this._errors.forEach(function (error) { return BABYLON.Tools.Error(error); });
-                        onError();
-                    }
-                    _this._clear();
-                };
-                this._addPendingData(this);
+                this._onSuccess = onSuccess;
+                this._onError = onError;
+                this.addPendingData(this);
                 this._loadScene(nodeNames);
                 this._loadAnimations();
-                this._removePendingData(this);
+                this.removePendingData(this);
+            };
+            GLTFLoader.prototype._onRenderReady = function () {
+                this._showMeshes();
+                this._startAnimations();
+                if (this._errors.length === 0) {
+                    this._onSuccess();
+                }
+                else {
+                    this._errors.forEach(function (error) { return BABYLON.Tools.Error(error); });
+                    this._errors = [];
+                    this._onError();
+                }
+            };
+            GLTFLoader.prototype._onLoaderComplete = function () {
+                this._errors.forEach(function (error) { return BABYLON.Tools.Error(error); });
+                this._errors = [];
+                this._clear();
             };
             GLTFLoader.prototype._loadData = function (data) {
                 this._gltf = data.json;
@@ -404,13 +411,6 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._clear = function () {
-                this._gltf = undefined;
-                this._pendingCount = 0;
-                this._onLoaded = undefined;
-                this._errors = [];
-                this._babylonScene = undefined;
-                this._rootUrl = undefined;
-                this._defaultMaterial = undefined;
                 // Revoke object urls created during load
                 if (this._gltf && this._gltf.textures) {
                     for (var i = 0; i < this._gltf.textures.length; i++) {
@@ -420,14 +420,42 @@ var BABYLON;
                         }
                     }
                 }
+                this._gltf = undefined;
+                this._errors = [];
+                this._babylonScene = undefined;
+                this._rootUrl = undefined;
+                this._defaultMaterial = undefined;
+                this._onSuccess = undefined;
+                this._onError = undefined;
+                this._renderReady = false;
+                this._renderPendingCount = 0;
+                this._loaderPendingCount = 0;
             };
             GLTFLoader.prototype._loadScene = function (nodeNames) {
                 var _this = this;
-                nodeNames = (nodeNames === "") ? null : nodeNames;
-                nodeNames = (nodeNames instanceof Array) ? nodeNames : [nodeNames];
                 var scene = this._gltf.scenes[this._gltf.scene || 0];
-                this._traverseScene(nodeNames, scene, function (node) { return _this._loadSkin(node); });
-                this._traverseScene(nodeNames, scene, function (node, parentNode) { return _this._loadMesh(node, parentNode); });
+                var nodeIndices = scene.nodes;
+                this._traverseNodes(nodeIndices, function (node, index, parentNode) {
+                    node.index = index;
+                    node.parent = parentNode;
+                    return true;
+                });
+                if (nodeNames) {
+                    if (!(nodeNames instanceof Array)) {
+                        nodeNames = [nodeNames];
+                    }
+                    var filteredNodeIndices = new Array();
+                    this._traverseNodes(nodeIndices, function (node) {
+                        if (nodeNames.indexOf(node.name) === -1) {
+                            return true;
+                        }
+                        filteredNodeIndices.push(node.index);
+                        return false;
+                    });
+                    nodeIndices = filteredNodeIndices;
+                }
+                this._traverseNodes(nodeIndices, function (node) { return _this._loadSkin(node); });
+                this._traverseNodes(nodeIndices, function (node) { return _this._loadMesh(node); });
             };
             GLTFLoader.prototype._loadSkin = function (node) {
                 var _this = this;
@@ -449,7 +477,7 @@ var BABYLON;
                     }
                     var accessor = this._gltf.accessors[skin.inverseBindMatrices];
                     this._loadAccessorAsync(accessor, function (data) {
-                        _this._traverseNode(null, skin.skeleton, function (node, parent) { return _this._updateBone(node, parent, skin, data); });
+                        _this._traverseNode(skin.skeleton, function (node, index, parent) { return _this._updateBone(node, parent, skin, data); });
                     });
                 }
                 return true;
@@ -478,7 +506,7 @@ var BABYLON;
                 node.babylonAnimationTargets.push(babylonBone);
                 return babylonBone;
             };
-            GLTFLoader.prototype._loadMesh = function (node, parentNode) {
+            GLTFLoader.prototype._loadMesh = function (node) {
                 var babylonMesh = new BABYLON.Mesh(node.name || "mesh" + node.index, this._babylonScene);
                 babylonMesh.isVisible = false;
                 this._loadTransform(node, babylonMesh);
@@ -486,7 +514,7 @@ var BABYLON;
                     var mesh = this._gltf.meshes[node.mesh];
                     this._loadMeshData(node, mesh, babylonMesh);
                 }
-                babylonMesh.parent = parentNode ? parentNode.babylonMesh : null;
+                babylonMesh.parent = node.parent ? node.parent.babylonMesh : null;
                 node.babylonMesh = babylonMesh;
                 node.babylonAnimationTargets = node.babylonAnimationTargets || [];
                 node.babylonAnimationTargets.push(node.babylonMesh);
@@ -502,17 +530,16 @@ var BABYLON;
             GLTFLoader.prototype._loadMeshData = function (node, mesh, babylonMesh) {
                 var _this = this;
                 babylonMesh.name = mesh.name || babylonMesh.name;
-                babylonMesh.subMeshes = [];
-                var multiMaterial = new BABYLON.MultiMaterial(babylonMesh.name, this._babylonScene);
-                babylonMesh.material = multiMaterial;
+                var babylonMultiMaterial = new BABYLON.MultiMaterial(babylonMesh.name, this._babylonScene);
+                babylonMesh.material = babylonMultiMaterial;
                 var geometry = new BABYLON.Geometry(babylonMesh.name, this._babylonScene, null, false, babylonMesh);
                 var vertexData = new BABYLON.VertexData();
                 vertexData.positions = [];
                 vertexData.indices = [];
                 var subMeshInfos = [];
-                var primitivesLoaded = 0;
-                var numPrimitives = mesh.primitives.length;
-                var _loop_1 = function () {
+                var loadedPrimitives = 0;
+                var totalPrimitives = mesh.primitives.length;
+                var _loop_1 = function (i) {
                     var primitive = mesh.primitives[i];
                     if (primitive.mode && primitive.mode !== GLTF2.EMeshPrimitiveMode.TRIANGLES) {
                         // TODO: handle other primitive modes
@@ -522,28 +549,40 @@ var BABYLON;
                     this_1._loadVertexDataAsync(primitive, function (subVertexData) {
                         _this._loadMorphTargetsData(mesh, primitive, subVertexData, babylonMesh);
                         subMeshInfos.push({
-                            materialIndex: multiMaterial.subMaterials.length,
+                            materialIndex: i,
                             verticesStart: vertexData.positions.length,
                             verticesCount: subVertexData.positions.length,
                             indicesStart: vertexData.indices.length,
                             indicesCount: subVertexData.indices.length
                         });
-                        var subMaterial = primitive.material === undefined ? _this._getDefaultMaterial() : GLTF2.GLTFLoaderExtension.LoadMaterial(primitive.material);
-                        multiMaterial.subMaterials.push(subMaterial);
                         vertexData.merge(subVertexData);
-                        if (++primitivesLoaded === numPrimitives) {
+                        if (primitive.material === undefined) {
+                            babylonMultiMaterial.subMaterials[i] = _this._getDefaultMaterial();
+                        }
+                        else {
+                            _this.loadMaterial(primitive.material, function (babylonSubMaterial) {
+                                if (_this._renderReady) {
+                                    babylonSubMaterial.forceCompilation(babylonMesh, function (babylonSubMaterial) {
+                                        babylonMultiMaterial.subMaterials[i] = babylonSubMaterial;
+                                    });
+                                }
+                                else {
+                                    babylonMultiMaterial.subMaterials[i] = babylonSubMaterial;
+                                }
+                            });
+                        }
+                        if (++loadedPrimitives === totalPrimitives) {
                             geometry.setAllVerticesData(vertexData, false);
-                            // Sub meshes must be created after setting vertex data because of mesh._createGlobalSubMesh.
-                            for (var i = 0; i < subMeshInfos.length; i++) {
-                                var info = subMeshInfos[i];
-                                new BABYLON.SubMesh(info.materialIndex, info.verticesStart, info.verticesCount, info.indicesStart, info.indicesCount, babylonMesh);
-                            }
+                            // TODO: optimize this so that sub meshes can be created without being overwritten after setting vertex data.
+                            // Sub meshes must be cleared and created after setting vertex data because of mesh._createGlobalSubMesh.
+                            babylonMesh.subMeshes = [];
+                            subMeshInfos.forEach(function (info) { return new BABYLON.SubMesh(info.materialIndex, info.verticesStart, info.verticesCount, info.indicesStart, info.indicesCount, babylonMesh); });
                         }
                     });
                 };
                 var this_1 = this;
-                for (var i = 0; i < numPrimitives; i++) {
-                    _loop_1();
+                for (var i = 0; i < totalPrimitives; i++) {
+                    _loop_1(i);
                 }
             };
             GLTFLoader.prototype._loadVertexDataAsync = function (primitive, onSuccess) {
@@ -555,7 +594,7 @@ var BABYLON;
                 }
                 var vertexData = new BABYLON.VertexData();
                 var loadedAttributes = 0;
-                var numAttributes = Object.keys(attributes).length;
+                var totalAttributes = Object.keys(attributes).length;
                 var _loop_2 = function (semantic) {
                     accessor = this_2._gltf.accessors[attributes[semantic]];
                     this_2._loadAccessorAsync(accessor, function (data) {
@@ -588,7 +627,7 @@ var BABYLON;
                                 BABYLON.Tools.Warn("Ignoring unrecognized semantic '" + semantic + "'");
                                 break;
                         }
-                        if (++loadedAttributes === numAttributes) {
+                        if (++loadedAttributes === totalAttributes) {
                             var indicesAccessor = _this._gltf.accessors[primitive.indices];
                             if (indicesAccessor) {
                                 _this._loadAccessorAsync(indicesAccessor, function (data) {
@@ -695,34 +734,21 @@ var BABYLON;
                 babylonMesh.rotationQuaternion = rotation;
                 babylonMesh.scaling = scaling;
             };
-            GLTFLoader.prototype._traverseScene = function (nodeNames, scene, action) {
-                var nodes = scene.nodes;
-                if (nodes) {
-                    for (var i = 0; i < nodes.length; i++) {
-                        this._traverseNode(nodeNames, nodes[i], action);
-                    }
+            GLTFLoader.prototype._traverseNodes = function (indices, action, parentNode) {
+                if (parentNode === void 0) { parentNode = null; }
+                for (var i = 0; i < indices.length; i++) {
+                    this._traverseNode(indices[i], action, parentNode);
                 }
             };
-            GLTFLoader.prototype._traverseNode = function (nodeNames, index, action, parentNode) {
+            GLTFLoader.prototype._traverseNode = function (index, action, parentNode) {
                 if (parentNode === void 0) { parentNode = null; }
                 var node = this._gltf.nodes[index];
-                if (nodeNames) {
-                    if (nodeNames.indexOf(node.name)) {
-                        // load all children
-                        nodeNames = null;
-                    }
-                    else {
-                        // skip this node tree
-                        return;
-                    }
-                }
-                node.index = index;
-                if (!action(node, parentNode)) {
+                if (!action(node, index, parentNode)) {
                     return;
                 }
                 if (node.children) {
                     for (var i = 0; i < node.children.length; i++) {
-                        this._traverseNode(nodeNames, node.children[i], action, node);
+                        this._traverseNode(node.children[i], action, node);
                     }
                 }
             };
@@ -851,11 +877,11 @@ var BABYLON;
             GLTFLoader.prototype._loadBufferAsync = function (index, onSuccess) {
                 var _this = this;
                 var buffer = this._gltf.buffers[index];
-                this._addPendingData(buffer);
+                this.addPendingData(buffer);
                 if (buffer.loadedData) {
                     setTimeout(function () {
                         onSuccess(buffer.loadedData);
-                        _this._removePendingData(buffer);
+                        _this.removePendingData(buffer);
                     });
                 }
                 else if (GLTF2.GLTFUtils.IsBase64(buffer.uri)) {
@@ -863,20 +889,20 @@ var BABYLON;
                     buffer.loadedData = new Uint8Array(data);
                     setTimeout(function () {
                         onSuccess(buffer.loadedData);
-                        _this._removePendingData(buffer);
+                        _this.removePendingData(buffer);
                     });
                 }
                 else if (buffer.loadedObservable) {
                     buffer.loadedObservable.add(function (buffer) {
                         onSuccess(buffer.loadedData);
-                        _this._removePendingData(buffer);
+                        _this.removePendingData(buffer);
                     });
                 }
                 else {
                     buffer.loadedObservable = new BABYLON.Observable();
                     buffer.loadedObservable.add(function (buffer) {
                         onSuccess(buffer.loadedData);
-                        _this._removePendingData(buffer);
+                        _this.removePendingData(buffer);
                     });
                     BABYLON.Tools.LoadFile(this._rootUrl + buffer.uri, function (data) {
                         buffer.loadedData = new Uint8Array(data);
@@ -884,7 +910,7 @@ var BABYLON;
                         buffer.loadedObservable = null;
                     }, null, null, true, function (request) {
                         _this._errors.push("Failed to load file '" + buffer.uri + "': " + request.statusText + "(" + request.status + ")");
-                        _this._removePendingData(buffer);
+                        _this.removePendingData(buffer);
                     });
                 }
             };
@@ -931,12 +957,27 @@ var BABYLON;
                 var byteLength = accessor.count * GLTF2.GLTFUtils.GetByteStrideFromType(accessor);
                 this._loadBufferViewAsync(bufferView, byteOffset, byteLength, accessor.componentType, onSuccess);
             };
-            GLTFLoader.prototype._addPendingData = function (data) {
-                this._pendingCount++;
+            GLTFLoader.prototype.addPendingData = function (data) {
+                if (!this._renderReady) {
+                    this._renderPendingCount++;
+                }
+                this.addLoaderPendingData(data);
+            };
+            GLTFLoader.prototype.removePendingData = function (data) {
+                if (!this._renderReady) {
+                    if (--this._renderPendingCount === 0) {
+                        this._renderReady = true;
+                        this._onRenderReady();
+                    }
+                }
+                this.removeLoaderPendingData(data);
+            };
+            GLTFLoader.prototype.addLoaderPendingData = function (data) {
+                this._loaderPendingCount++;
             };
-            GLTFLoader.prototype._removePendingData = function (data) {
-                if (--this._pendingCount === 0) {
-                    this._onLoaded();
+            GLTFLoader.prototype.removeLoaderPendingData = function (data) {
+                if (--this._loaderPendingCount === 0) {
+                    this._onLoaderComplete();
                 }
             };
             GLTFLoader.prototype._getDefaultMaterial = function () {
@@ -953,46 +994,49 @@ var BABYLON;
                 }
                 return this._defaultMaterial;
             };
-            GLTFLoader.prototype._loadMaterial = function (index) {
-                var materials = this._gltf.materials;
-                var material = materials ? materials[index] : null;
-                if (!material) {
-                    BABYLON.Tools.Warn("Material index (" + index + ") does not exist");
-                    return null;
-                }
-                material.babylonMaterial = new BABYLON.PBRMaterial(material.name || "mat" + index, this._babylonScene);
-                material.babylonMaterial.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation;
-                material.babylonMaterial.useScalarInLinearSpace = true;
-                return material;
-            };
-            GLTFLoader.prototype._loadCoreMaterial = function (index) {
-                var material = this._loadMaterial(index);
-                if (!material) {
-                    return null;
-                }
-                this._loadCommonMaterialProperties(material);
+            GLTFLoader.prototype._loadMaterialMetallicRoughnessProperties = function (material) {
                 // Ensure metallic workflow
                 material.babylonMaterial.metallic = 1;
                 material.babylonMaterial.roughness = 1;
                 var properties = material.pbrMetallicRoughness;
-                if (properties) {
-                    material.babylonMaterial.albedoColor = properties.baseColorFactor ? BABYLON.Color3.FromArray(properties.baseColorFactor) : new BABYLON.Color3(1, 1, 1);
-                    material.babylonMaterial.metallic = properties.metallicFactor === undefined ? 1 : properties.metallicFactor;
-                    material.babylonMaterial.roughness = properties.roughnessFactor === undefined ? 1 : properties.roughnessFactor;
-                    if (properties.baseColorTexture) {
-                        material.babylonMaterial.albedoTexture = this._loadTexture(properties.baseColorTexture);
-                        this._loadAlphaProperties(material);
-                    }
-                    if (properties.metallicRoughnessTexture) {
-                        material.babylonMaterial.metallicTexture = this._loadTexture(properties.metallicRoughnessTexture);
-                        material.babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
-                        material.babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
-                        material.babylonMaterial.useRoughnessFromMetallicTextureAlpha = false;
-                    }
+                if (!properties) {
+                    return;
+                }
+                material.babylonMaterial.albedoColor = properties.baseColorFactor ? BABYLON.Color3.FromArray(properties.baseColorFactor) : new BABYLON.Color3(1, 1, 1);
+                material.babylonMaterial.metallic = properties.metallicFactor === undefined ? 1 : properties.metallicFactor;
+                material.babylonMaterial.roughness = properties.roughnessFactor === undefined ? 1 : properties.roughnessFactor;
+                if (properties.baseColorTexture) {
+                    material.babylonMaterial.albedoTexture = this.loadTexture(properties.baseColorTexture);
+                    this.loadMaterialAlphaProperties(material);
+                }
+                if (properties.metallicRoughnessTexture) {
+                    material.babylonMaterial.metallicTexture = this.loadTexture(properties.metallicRoughnessTexture);
+                    material.babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
+                    material.babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
+                    material.babylonMaterial.useRoughnessFromMetallicTextureAlpha = false;
+                }
+            };
+            GLTFLoader.prototype.loadMaterial = function (index, assign) {
+                var material = this._gltf.materials[index];
+                material.index = index;
+                if (material.babylonMaterial) {
+                    assign(material.babylonMaterial);
+                    return;
+                }
+                if (GLTF2.GLTFLoaderExtension.LoadMaterial(this, material, assign)) {
+                    return;
                 }
-                return material.babylonMaterial;
+                this.createPbrMaterial(material);
+                this.loadMaterialBaseProperties(material);
+                this._loadMaterialMetallicRoughnessProperties(material);
+                assign(material.babylonMaterial);
+            };
+            GLTFLoader.prototype.createPbrMaterial = function (material) {
+                material.babylonMaterial = new BABYLON.PBRMaterial(material.name || "mat" + material.index, this._babylonScene);
+                material.babylonMaterial.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation;
+                material.babylonMaterial.useScalarInLinearSpace = true;
             };
-            GLTFLoader.prototype._loadCommonMaterialProperties = function (material) {
+            GLTFLoader.prototype.loadMaterialBaseProperties = function (material) {
                 material.babylonMaterial.useEmissiveAsIllumination = (material.emissiveFactor || material.emissiveTexture) ? true : false;
                 material.babylonMaterial.emissiveColor = material.emissiveFactor ? BABYLON.Color3.FromArray(material.emissiveFactor) : new BABYLON.Color3(0, 0, 0);
                 if (material.doubleSided) {
@@ -1000,23 +1044,23 @@ var BABYLON;
                     material.babylonMaterial.twoSidedLighting = true;
                 }
                 if (material.normalTexture) {
-                    material.babylonMaterial.bumpTexture = this._loadTexture(material.normalTexture);
+                    material.babylonMaterial.bumpTexture = this.loadTexture(material.normalTexture);
                     if (material.normalTexture.scale !== undefined) {
                         material.babylonMaterial.bumpTexture.level = material.normalTexture.scale;
                     }
                 }
                 if (material.occlusionTexture) {
-                    material.babylonMaterial.ambientTexture = this._loadTexture(material.occlusionTexture);
+                    material.babylonMaterial.ambientTexture = this.loadTexture(material.occlusionTexture);
                     material.babylonMaterial.useAmbientInGrayScale = true;
                     if (material.occlusionTexture.strength !== undefined) {
                         material.babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
                     }
                 }
                 if (material.emissiveTexture) {
-                    material.babylonMaterial.emissiveTexture = this._loadTexture(material.emissiveTexture);
+                    material.babylonMaterial.emissiveTexture = this.loadTexture(material.emissiveTexture);
                 }
             };
-            GLTFLoader.prototype._loadAlphaProperties = function (material) {
+            GLTFLoader.prototype.loadMaterialAlphaProperties = function (material) {
                 var alphaMode = material.alphaMode || "OPAQUE";
                 switch (alphaMode) {
                     case "OPAQUE":
@@ -1025,18 +1069,17 @@ var BABYLON;
                     case "MASK":
                         material.babylonMaterial.albedoTexture.hasAlpha = true;
                         material.babylonMaterial.useAlphaFromAlbedoTexture = false;
-                        material.babylonMaterial.alphaMode = BABYLON.Engine.ALPHA_DISABLE;
                         break;
                     case "BLEND":
                         material.babylonMaterial.albedoTexture.hasAlpha = true;
                         material.babylonMaterial.useAlphaFromAlbedoTexture = true;
-                        material.babylonMaterial.alphaMode = BABYLON.Engine.ALPHA_COMBINE;
                         break;
                     default:
-                        BABYLON.Tools.Error("Invalid alpha mode '" + material.alphaMode + "'");
+                        BABYLON.Tools.Warn("Invalid alpha mode '" + material.alphaMode + "'");
+                        break;
                 }
             };
-            GLTFLoader.prototype._loadTexture = function (textureInfo) {
+            GLTFLoader.prototype.loadTexture = function (textureInfo) {
                 var _this = this;
                 var texture = this._gltf.textures[textureInfo.index];
                 var texCoord = textureInfo.texCoord || 0;
@@ -1079,12 +1122,12 @@ var BABYLON;
                 var sampler = (texture.sampler === undefined ? {} : this._gltf.samplers[texture.sampler]);
                 var noMipMaps = (sampler.minFilter === GLTF2.ETextureMinFilter.NEAREST || sampler.minFilter === GLTF2.ETextureMinFilter.LINEAR);
                 var samplingMode = GLTF2.GLTFUtils.GetTextureFilterMode(sampler.minFilter);
-                this._addPendingData(texture);
+                this.addPendingData(texture);
                 var babylonTexture = new BABYLON.Texture(url, this._babylonScene, noMipMaps, false, samplingMode, function () {
-                    _this._removePendingData(texture);
+                    _this.removePendingData(texture);
                 }, function () {
                     _this._errors.push("Failed to load texture '" + source.uri + "'");
-                    _this._removePendingData(texture);
+                    _this.removePendingData(texture);
                 });
                 babylonTexture.coordinatesIndex = texCoord;
                 babylonTexture.wrapU = GLTF2.GLTFUtils.GetWrapMode(sampler.wrapS);
@@ -1205,42 +1248,39 @@ var BABYLON;
     var GLTF2;
     (function (GLTF2) {
         var GLTFLoaderExtension = (function () {
-            function GLTFLoaderExtension(name) {
+            function GLTFLoaderExtension() {
                 this.enabled = true;
-                this._name = name;
             }
-            Object.defineProperty(GLTFLoaderExtension.prototype, "name", {
-                get: function () {
-                    return this._name;
-                },
-                enumerable: true,
-                configurable: true
-            });
-            GLTFLoaderExtension.prototype.loadMaterial = function (index) { return null; };
-            // ---------
-            // Utilities
-            // ---------
-            GLTFLoaderExtension.LoadMaterial = function (index) {
-                for (var extensionName in GLTF2.GLTFLoader.Extensions) {
-                    var extension = GLTF2.GLTFLoader.Extensions[extensionName];
-                    if (extension.enabled) {
-                        var babylonMaterial = extension.loadMaterial(index);
-                        if (babylonMaterial) {
-                            return babylonMaterial;
-                        }
+            GLTFLoaderExtension.prototype.loadMaterial = function (loader, material, assign) { return false; };
+            GLTFLoaderExtension.LoadMaterial = function (loader, material, assign) {
+                return this._ApplyExtensions(function (extension) { return extension.loadMaterial(loader, material, assign); });
+            };
+            GLTFLoaderExtension._ApplyExtensions = function (action) {
+                var extensions = GLTFLoaderExtension._Extensions;
+                if (!extensions) {
+                    return;
+                }
+                for (var i = 0; i < extensions.length; i++) {
+                    var extension = extensions[i];
+                    if (extension.enabled && action(extension)) {
+                        return true;
                     }
                 }
-                return GLTF2.GLTFLoader.LoadCoreMaterial(index);
+                return false;
             };
             return GLTFLoaderExtension;
         }());
+        //
+        // Utilities
+        //
+        GLTFLoaderExtension._Extensions = [];
         GLTF2.GLTFLoaderExtension = GLTFLoaderExtension;
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
 //# sourceMappingURL=babylon.glTFLoaderExtension.js.map
 
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+/// <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; }) ||
@@ -1255,43 +1295,122 @@ var BABYLON;
 (function (BABYLON) {
     var GLTF2;
     (function (GLTF2) {
-        var GLTFMaterialsPbrSpecularGlossinessExtension = (function (_super) {
-            __extends(GLTFMaterialsPbrSpecularGlossinessExtension, _super);
-            function GLTFMaterialsPbrSpecularGlossinessExtension() {
-                return _super.call(this, "KHR_materials_pbrSpecularGlossiness") || this;
-            }
-            GLTFMaterialsPbrSpecularGlossinessExtension.prototype.loadMaterial = function (index) {
-                var material = GLTF2.GLTFLoader.LoadMaterial(index);
-                if (!material || !material.extensions)
-                    return null;
-                var properties = material.extensions[this.name];
-                if (!properties)
-                    return null;
-                GLTF2.GLTFLoader.LoadCommonMaterialProperties(material);
-                //
-                // Load Factors
-                //
-                material.babylonMaterial.albedoColor = properties.diffuseFactor ? BABYLON.Color3.FromArray(properties.diffuseFactor) : new BABYLON.Color3(1, 1, 1);
-                material.babylonMaterial.reflectivityColor = properties.specularFactor ? BABYLON.Color3.FromArray(properties.specularFactor) : new BABYLON.Color3(1, 1, 1);
-                material.babylonMaterial.microSurface = properties.glossinessFactor === undefined ? 1 : properties.glossinessFactor;
-                //
-                // Load Textures
-                //
-                if (properties.diffuseTexture) {
-                    material.babylonMaterial.albedoTexture = GLTF2.GLTFLoader.LoadTexture(properties.diffuseTexture);
-                    GLTF2.GLTFLoader.LoadAlphaProperties(material);
-                }
-                if (properties.specularGlossinessTexture) {
-                    material.babylonMaterial.reflectivityTexture = GLTF2.GLTFLoader.LoadTexture(properties.specularGlossinessTexture);
-                    material.babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
-                }
-                return material.babylonMaterial;
-            };
-            return GLTFMaterialsPbrSpecularGlossinessExtension;
-        }(GLTF2.GLTFLoaderExtension));
-        GLTF2.GLTFMaterialsPbrSpecularGlossinessExtension = GLTFMaterialsPbrSpecularGlossinessExtension;
-        GLTF2.GLTFLoader.RegisterExtension(new GLTFMaterialsPbrSpecularGlossinessExtension());
+        var Extensions;
+        (function (Extensions) {
+            var MSFTLOD = (function (_super) {
+                __extends(MSFTLOD, _super);
+                function MSFTLOD() {
+                    return _super !== null && _super.apply(this, arguments) || this;
+                }
+                Object.defineProperty(MSFTLOD.prototype, "name", {
+                    get: function () {
+                        return "MSFT_lod";
+                    },
+                    enumerable: true,
+                    configurable: true
+                });
+                MSFTLOD.prototype.loadMaterial = function (loader, material, assign) {
+                    if (!material.extensions) {
+                        return false;
+                    }
+                    var properties = material.extensions[this.name];
+                    if (!properties) {
+                        return false;
+                    }
+                    // Clear out the extension so that it won't get loaded again.
+                    material.extensions[this.name] = undefined;
+                    // Tell the loader not to clear its state until the highest LOD is loaded.
+                    loader.addLoaderPendingData(material);
+                    // Start with the lowest quality LOD.
+                    var materialLODs = [material.index].concat(properties.ids);
+                    this.loadMaterialLOD(loader, material, materialLODs, materialLODs.length - 1, assign);
+                    return true;
+                };
+                MSFTLOD.prototype.loadMaterialLOD = function (loader, material, materialLODs, lod, assign) {
+                    var _this = this;
+                    loader.loadMaterial(materialLODs[lod], function (babylonMaterial) {
+                        babylonMaterial.name += ".LOD" + lod;
+                        assign(babylonMaterial);
+                        // Loading is complete if this is the highest quality LOD.
+                        if (lod === 0) {
+                            loader.removeLoaderPendingData(material);
+                            return;
+                        }
+                        // Load the next LOD when all of the textures are loaded.
+                        BABYLON.BaseTexture.WhenAllReady(babylonMaterial.getActiveTextures(), function () {
+                            _this.loadMaterialLOD(loader, material, materialLODs, lod - 1, assign);
+                        });
+                    });
+                };
+                return MSFTLOD;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.MSFTLOD = MSFTLOD;
+            GLTF2.GLTFLoader.RegisterExtension(new MSFTLOD());
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=MSFT_lod.js.map
+
+/// <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 GLTF2;
+    (function (GLTF2) {
+        var Extensions;
+        (function (Extensions) {
+            var KHRMaterialsPbrSpecularGlossiness = (function (_super) {
+                __extends(KHRMaterialsPbrSpecularGlossiness, _super);
+                function KHRMaterialsPbrSpecularGlossiness() {
+                    return _super !== null && _super.apply(this, arguments) || this;
+                }
+                Object.defineProperty(KHRMaterialsPbrSpecularGlossiness.prototype, "name", {
+                    get: function () {
+                        return "KHR_materials_pbrSpecularGlossiness";
+                    },
+                    enumerable: true,
+                    configurable: true
+                });
+                KHRMaterialsPbrSpecularGlossiness.prototype.loadMaterial = function (loader, material, assign) {
+                    if (!material.extensions) {
+                        return false;
+                    }
+                    var properties = material.extensions[this.name];
+                    if (!properties) {
+                        return false;
+                    }
+                    loader.createPbrMaterial(material);
+                    loader.loadMaterialBaseProperties(material);
+                    material.babylonMaterial.albedoColor = properties.diffuseFactor ? BABYLON.Color3.FromArray(properties.diffuseFactor) : new BABYLON.Color3(1, 1, 1);
+                    material.babylonMaterial.reflectivityColor = properties.specularFactor ? BABYLON.Color3.FromArray(properties.specularFactor) : new BABYLON.Color3(1, 1, 1);
+                    material.babylonMaterial.microSurface = properties.glossinessFactor === undefined ? 1 : properties.glossinessFactor;
+                    if (properties.diffuseTexture) {
+                        material.babylonMaterial.albedoTexture = loader.loadTexture(properties.diffuseTexture);
+                        loader.loadMaterialAlphaProperties(material);
+                    }
+                    if (properties.specularGlossinessTexture) {
+                        material.babylonMaterial.reflectivityTexture = loader.loadTexture(properties.specularGlossinessTexture);
+                        material.babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
+                    }
+                    assign(material.babylonMaterial);
+                    return true;
+                };
+                return KHRMaterialsPbrSpecularGlossiness;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.KHRMaterialsPbrSpecularGlossiness = KHRMaterialsPbrSpecularGlossiness;
+            GLTF2.GLTFLoader.RegisterExtension(new KHRMaterialsPbrSpecularGlossiness());
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
-//# sourceMappingURL=babylon.glTFMaterialsPbrSpecularGlossinessExtension.js.map
+//# sourceMappingURL=KHR_materials_pbrSpecularGlossiness.js.map

Різницю між файлами не показано, бо вона завелика
+ 1 - 5
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 42 - 30
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -615,15 +615,11 @@ declare module BABYLON.GLTF2 {
         samplers: IGLTFAnimationSampler[];
         targets?: any[];
     }
-    interface IGLTFAssetProfile extends IGLTFProperty {
-        api?: string;
-        version?: string;
-    }
     interface IGLTFAsset extends IGLTFChildRootProperty {
         copyright?: string;
         generator?: string;
-        profile?: IGLTFAssetProfile;
         version: string;
+        minVersion?: string;
     }
     interface IGLTFBuffer extends IGLTFChildRootProperty {
         uri?: string;
@@ -681,6 +677,7 @@ declare module BABYLON.GLTF2 {
         alphaMode?: string;
         alphaCutoff: number;
         doubleSided?: boolean;
+        index?: number;
         babylonMaterial?: PBRMaterial;
     }
     interface IGLTFMeshPrimitive extends IGLTFProperty {
@@ -709,6 +706,7 @@ declare module BABYLON.GLTF2 {
         translation?: number[];
         weights?: number[];
         index?: number;
+        parent?: IGLTFNode;
         babylonMesh?: Mesh;
         babylonSkinToBones?: {
             [skin: number]: Bone;
@@ -767,24 +765,26 @@ declare module BABYLON.GLTF2 {
 declare module BABYLON.GLTF2 {
     class GLTFLoader implements IGLTFLoader {
         private _gltf;
-        private _pendingCount;
-        private _onLoaded;
         private _errors;
         private _babylonScene;
         private _rootUrl;
         private _defaultMaterial;
+        private _onSuccess;
+        private _onError;
+        private _renderReady;
+        private _renderPendingCount;
+        private _loaderPendingCount;
         static Extensions: {
             [name: string]: GLTFLoaderExtension;
         };
         static RegisterExtension(extension: GLTFLoaderExtension): void;
-        static LoadMaterial(index: number): IGLTFMaterial;
-        static LoadCoreMaterial(index: number): Material;
-        static LoadCommonMaterialProperties(material: IGLTFMaterial): void;
-        static LoadAlphaProperties(material: IGLTFMaterial): void;
-        static LoadTexture(textureInfo: IGLTFTextureInfo): Texture;
+        readonly gltf: IGLTF;
+        readonly babylonScene: Scene;
         importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void): void;
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void): void;
         private _loadAsync(nodeNames, scene, data, rootUrl, onSuccess, onError);
+        private _onRenderReady();
+        private _onLoaderComplete();
         private _loadData(data);
         private _showMeshes();
         private _startAnimations();
@@ -793,27 +793,30 @@ declare module BABYLON.GLTF2 {
         private _loadSkin(node);
         private _updateBone(node, parentNode, skin, inverseBindMatrixData);
         private _createBone(node, skin);
-        private _loadMesh(node, parentNode);
+        private _loadMesh(node);
         private _loadMeshData(node, mesh, babylonMesh);
         private _loadVertexDataAsync(primitive, onSuccess);
         private _createMorphTargets(node, mesh, primitive, babylonMesh);
         private _loadMorphTargetsData(mesh, primitive, vertexData, babylonMesh);
         private _loadTransform(node, babylonMesh);
-        private _traverseScene(nodeNames, scene, action);
-        private _traverseNode(nodeNames, index, action, parentNode?);
+        private _traverseNodes(indices, action, parentNode?);
+        private _traverseNode(index, action, parentNode?);
         private _loadAnimations();
         private _loadAnimationChannel(animation, animationIndex, channelIndex);
         private _loadBufferAsync(index, onSuccess);
         private _loadBufferViewAsync(bufferView, byteOffset, byteLength, componentType, onSuccess);
         private _loadAccessorAsync(accessor, onSuccess);
-        private _addPendingData(data);
-        private _removePendingData(data);
+        addPendingData(data: any): void;
+        removePendingData(data: any): void;
+        addLoaderPendingData(data: any): void;
+        removeLoaderPendingData(data: any): void;
         private _getDefaultMaterial();
-        private _loadMaterial(index);
-        private _loadCoreMaterial(index);
-        private _loadCommonMaterialProperties(material);
-        private _loadAlphaProperties(material);
-        private _loadTexture(textureInfo);
+        private _loadMaterialMetallicRoughnessProperties(material);
+        loadMaterial(index: number, assign: (material: Material) => void): void;
+        createPbrMaterial(material: IGLTFMaterial): void;
+        loadMaterialBaseProperties(material: IGLTFMaterial): void;
+        loadMaterialAlphaProperties(material: IGLTFMaterial): void;
+        loadTexture(textureInfo: IGLTFTextureInfo): Texture;
     }
 }
 
@@ -859,19 +862,28 @@ declare module BABYLON.GLTF2 {
 
 declare module BABYLON.GLTF2 {
     abstract class GLTFLoaderExtension {
-        private _name;
         enabled: boolean;
-        constructor(name: string);
+        readonly abstract name: string;
+        protected loadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean;
+        static _Extensions: GLTFLoaderExtension[];
+        static LoadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean;
+        private static _ApplyExtensions(action);
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    class MSFTLOD extends GLTFLoaderExtension {
         readonly name: string;
-        protected loadMaterial(index: number): Material;
-        static LoadMaterial(index: number): Material;
+        protected loadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean;
+        private loadMaterialLOD(loader, material, materialLODs, lod, assign);
     }
 }
 
 
-declare module BABYLON.GLTF2 {
-    class GLTFMaterialsPbrSpecularGlossinessExtension extends GLTFLoaderExtension {
-        constructor();
-        protected loadMaterial(index: number): Material;
+declare module BABYLON.GLTF2.Extensions {
+    class KHRMaterialsPbrSpecularGlossiness extends GLTFLoaderExtension {
+        readonly name: string;
+        protected loadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean;
     }
 }

+ 319 - 200
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -2448,23 +2448,24 @@ var BABYLON;
                     BABYLON.Tools.Error("Extension with the same name '" + extension.name + "' already exists");
                     return;
                 }
-                this.Extensions[extension.name] = extension;
-            };
-            GLTFLoader.LoadMaterial = function (index) {
-                return BABYLON.GLTFFileLoader.GLTFLoaderV2._loadMaterial(index);
-            };
-            GLTFLoader.LoadCoreMaterial = function (index) {
-                return BABYLON.GLTFFileLoader.GLTFLoaderV2._loadCoreMaterial(index);
-            };
-            GLTFLoader.LoadCommonMaterialProperties = function (material) {
-                return BABYLON.GLTFFileLoader.GLTFLoaderV2._loadCommonMaterialProperties(material);
-            };
-            GLTFLoader.LoadAlphaProperties = function (material) {
-                return BABYLON.GLTFFileLoader.GLTFLoaderV2._loadAlphaProperties(material);
-            };
-            GLTFLoader.LoadTexture = function (textureInfo) {
-                return BABYLON.GLTFFileLoader.GLTFLoaderV2._loadTexture(textureInfo);
+                GLTFLoader.Extensions[extension.name] = extension;
+                // Keep the order of registration so that extensions registered first are called first.
+                GLTF2.GLTFLoaderExtension._Extensions.push(extension);
             };
+            Object.defineProperty(GLTFLoader.prototype, "gltf", {
+                get: function () {
+                    return this._gltf;
+                },
+                enumerable: true,
+                configurable: true
+            });
+            Object.defineProperty(GLTFLoader.prototype, "babylonScene", {
+                get: function () {
+                    return this._babylonScene;
+                },
+                enumerable: true,
+                configurable: true
+            });
             GLTFLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onSuccess, onError) {
                 var _this = this;
                 this._loadAsync(meshesNames, scene, data, rootUrl, function () {
@@ -2493,28 +2494,34 @@ var BABYLON;
                 this._loadAsync(null, scene, data, rootUrl, onSuccess, onError);
             };
             GLTFLoader.prototype._loadAsync = function (nodeNames, scene, data, rootUrl, onSuccess, onError) {
-                var _this = this;
                 scene.useRightHandedSystem = true;
                 this._clear();
                 this._loadData(data);
                 this._babylonScene = scene;
                 this._rootUrl = rootUrl;
-                this._onLoaded = function () {
-                    _this._showMeshes();
-                    _this._startAnimations();
-                    if (_this._errors.length === 0) {
-                        onSuccess();
-                    }
-                    else {
-                        _this._errors.forEach(function (error) { return BABYLON.Tools.Error(error); });
-                        onError();
-                    }
-                    _this._clear();
-                };
-                this._addPendingData(this);
+                this._onSuccess = onSuccess;
+                this._onError = onError;
+                this.addPendingData(this);
                 this._loadScene(nodeNames);
                 this._loadAnimations();
-                this._removePendingData(this);
+                this.removePendingData(this);
+            };
+            GLTFLoader.prototype._onRenderReady = function () {
+                this._showMeshes();
+                this._startAnimations();
+                if (this._errors.length === 0) {
+                    this._onSuccess();
+                }
+                else {
+                    this._errors.forEach(function (error) { return BABYLON.Tools.Error(error); });
+                    this._errors = [];
+                    this._onError();
+                }
+            };
+            GLTFLoader.prototype._onLoaderComplete = function () {
+                this._errors.forEach(function (error) { return BABYLON.Tools.Error(error); });
+                this._errors = [];
+                this._clear();
             };
             GLTFLoader.prototype._loadData = function (data) {
                 this._gltf = data.json;
@@ -2557,13 +2564,6 @@ var BABYLON;
                 }
             };
             GLTFLoader.prototype._clear = function () {
-                this._gltf = undefined;
-                this._pendingCount = 0;
-                this._onLoaded = undefined;
-                this._errors = [];
-                this._babylonScene = undefined;
-                this._rootUrl = undefined;
-                this._defaultMaterial = undefined;
                 // Revoke object urls created during load
                 if (this._gltf && this._gltf.textures) {
                     for (var i = 0; i < this._gltf.textures.length; i++) {
@@ -2573,14 +2573,42 @@ var BABYLON;
                         }
                     }
                 }
+                this._gltf = undefined;
+                this._errors = [];
+                this._babylonScene = undefined;
+                this._rootUrl = undefined;
+                this._defaultMaterial = undefined;
+                this._onSuccess = undefined;
+                this._onError = undefined;
+                this._renderReady = false;
+                this._renderPendingCount = 0;
+                this._loaderPendingCount = 0;
             };
             GLTFLoader.prototype._loadScene = function (nodeNames) {
                 var _this = this;
-                nodeNames = (nodeNames === "") ? null : nodeNames;
-                nodeNames = (nodeNames instanceof Array) ? nodeNames : [nodeNames];
                 var scene = this._gltf.scenes[this._gltf.scene || 0];
-                this._traverseScene(nodeNames, scene, function (node) { return _this._loadSkin(node); });
-                this._traverseScene(nodeNames, scene, function (node, parentNode) { return _this._loadMesh(node, parentNode); });
+                var nodeIndices = scene.nodes;
+                this._traverseNodes(nodeIndices, function (node, index, parentNode) {
+                    node.index = index;
+                    node.parent = parentNode;
+                    return true;
+                });
+                if (nodeNames) {
+                    if (!(nodeNames instanceof Array)) {
+                        nodeNames = [nodeNames];
+                    }
+                    var filteredNodeIndices = new Array();
+                    this._traverseNodes(nodeIndices, function (node) {
+                        if (nodeNames.indexOf(node.name) === -1) {
+                            return true;
+                        }
+                        filteredNodeIndices.push(node.index);
+                        return false;
+                    });
+                    nodeIndices = filteredNodeIndices;
+                }
+                this._traverseNodes(nodeIndices, function (node) { return _this._loadSkin(node); });
+                this._traverseNodes(nodeIndices, function (node) { return _this._loadMesh(node); });
             };
             GLTFLoader.prototype._loadSkin = function (node) {
                 var _this = this;
@@ -2602,7 +2630,7 @@ var BABYLON;
                     }
                     var accessor = this._gltf.accessors[skin.inverseBindMatrices];
                     this._loadAccessorAsync(accessor, function (data) {
-                        _this._traverseNode(null, skin.skeleton, function (node, parent) { return _this._updateBone(node, parent, skin, data); });
+                        _this._traverseNode(skin.skeleton, function (node, index, parent) { return _this._updateBone(node, parent, skin, data); });
                     });
                 }
                 return true;
@@ -2631,7 +2659,7 @@ var BABYLON;
                 node.babylonAnimationTargets.push(babylonBone);
                 return babylonBone;
             };
-            GLTFLoader.prototype._loadMesh = function (node, parentNode) {
+            GLTFLoader.prototype._loadMesh = function (node) {
                 var babylonMesh = new BABYLON.Mesh(node.name || "mesh" + node.index, this._babylonScene);
                 babylonMesh.isVisible = false;
                 this._loadTransform(node, babylonMesh);
@@ -2639,7 +2667,7 @@ var BABYLON;
                     var mesh = this._gltf.meshes[node.mesh];
                     this._loadMeshData(node, mesh, babylonMesh);
                 }
-                babylonMesh.parent = parentNode ? parentNode.babylonMesh : null;
+                babylonMesh.parent = node.parent ? node.parent.babylonMesh : null;
                 node.babylonMesh = babylonMesh;
                 node.babylonAnimationTargets = node.babylonAnimationTargets || [];
                 node.babylonAnimationTargets.push(node.babylonMesh);
@@ -2655,17 +2683,16 @@ var BABYLON;
             GLTFLoader.prototype._loadMeshData = function (node, mesh, babylonMesh) {
                 var _this = this;
                 babylonMesh.name = mesh.name || babylonMesh.name;
-                babylonMesh.subMeshes = [];
-                var multiMaterial = new BABYLON.MultiMaterial(babylonMesh.name, this._babylonScene);
-                babylonMesh.material = multiMaterial;
+                var babylonMultiMaterial = new BABYLON.MultiMaterial(babylonMesh.name, this._babylonScene);
+                babylonMesh.material = babylonMultiMaterial;
                 var geometry = new BABYLON.Geometry(babylonMesh.name, this._babylonScene, null, false, babylonMesh);
                 var vertexData = new BABYLON.VertexData();
                 vertexData.positions = [];
                 vertexData.indices = [];
                 var subMeshInfos = [];
-                var primitivesLoaded = 0;
-                var numPrimitives = mesh.primitives.length;
-                var _loop_1 = function () {
+                var loadedPrimitives = 0;
+                var totalPrimitives = mesh.primitives.length;
+                var _loop_1 = function (i) {
                     var primitive = mesh.primitives[i];
                     if (primitive.mode && primitive.mode !== GLTF2.EMeshPrimitiveMode.TRIANGLES) {
                         // TODO: handle other primitive modes
@@ -2675,28 +2702,40 @@ var BABYLON;
                     this_1._loadVertexDataAsync(primitive, function (subVertexData) {
                         _this._loadMorphTargetsData(mesh, primitive, subVertexData, babylonMesh);
                         subMeshInfos.push({
-                            materialIndex: multiMaterial.subMaterials.length,
+                            materialIndex: i,
                             verticesStart: vertexData.positions.length,
                             verticesCount: subVertexData.positions.length,
                             indicesStart: vertexData.indices.length,
                             indicesCount: subVertexData.indices.length
                         });
-                        var subMaterial = primitive.material === undefined ? _this._getDefaultMaterial() : GLTF2.GLTFLoaderExtension.LoadMaterial(primitive.material);
-                        multiMaterial.subMaterials.push(subMaterial);
                         vertexData.merge(subVertexData);
-                        if (++primitivesLoaded === numPrimitives) {
+                        if (primitive.material === undefined) {
+                            babylonMultiMaterial.subMaterials[i] = _this._getDefaultMaterial();
+                        }
+                        else {
+                            _this.loadMaterial(primitive.material, function (babylonSubMaterial) {
+                                if (_this._renderReady) {
+                                    babylonSubMaterial.forceCompilation(babylonMesh, function (babylonSubMaterial) {
+                                        babylonMultiMaterial.subMaterials[i] = babylonSubMaterial;
+                                    });
+                                }
+                                else {
+                                    babylonMultiMaterial.subMaterials[i] = babylonSubMaterial;
+                                }
+                            });
+                        }
+                        if (++loadedPrimitives === totalPrimitives) {
                             geometry.setAllVerticesData(vertexData, false);
-                            // Sub meshes must be created after setting vertex data because of mesh._createGlobalSubMesh.
-                            for (var i = 0; i < subMeshInfos.length; i++) {
-                                var info = subMeshInfos[i];
-                                new BABYLON.SubMesh(info.materialIndex, info.verticesStart, info.verticesCount, info.indicesStart, info.indicesCount, babylonMesh);
-                            }
+                            // TODO: optimize this so that sub meshes can be created without being overwritten after setting vertex data.
+                            // Sub meshes must be cleared and created after setting vertex data because of mesh._createGlobalSubMesh.
+                            babylonMesh.subMeshes = [];
+                            subMeshInfos.forEach(function (info) { return new BABYLON.SubMesh(info.materialIndex, info.verticesStart, info.verticesCount, info.indicesStart, info.indicesCount, babylonMesh); });
                         }
                     });
                 };
                 var this_1 = this;
-                for (var i = 0; i < numPrimitives; i++) {
-                    _loop_1();
+                for (var i = 0; i < totalPrimitives; i++) {
+                    _loop_1(i);
                 }
             };
             GLTFLoader.prototype._loadVertexDataAsync = function (primitive, onSuccess) {
@@ -2708,7 +2747,7 @@ var BABYLON;
                 }
                 var vertexData = new BABYLON.VertexData();
                 var loadedAttributes = 0;
-                var numAttributes = Object.keys(attributes).length;
+                var totalAttributes = Object.keys(attributes).length;
                 var _loop_2 = function (semantic) {
                     accessor = this_2._gltf.accessors[attributes[semantic]];
                     this_2._loadAccessorAsync(accessor, function (data) {
@@ -2741,7 +2780,7 @@ var BABYLON;
                                 BABYLON.Tools.Warn("Ignoring unrecognized semantic '" + semantic + "'");
                                 break;
                         }
-                        if (++loadedAttributes === numAttributes) {
+                        if (++loadedAttributes === totalAttributes) {
                             var indicesAccessor = _this._gltf.accessors[primitive.indices];
                             if (indicesAccessor) {
                                 _this._loadAccessorAsync(indicesAccessor, function (data) {
@@ -2848,34 +2887,21 @@ var BABYLON;
                 babylonMesh.rotationQuaternion = rotation;
                 babylonMesh.scaling = scaling;
             };
-            GLTFLoader.prototype._traverseScene = function (nodeNames, scene, action) {
-                var nodes = scene.nodes;
-                if (nodes) {
-                    for (var i = 0; i < nodes.length; i++) {
-                        this._traverseNode(nodeNames, nodes[i], action);
-                    }
+            GLTFLoader.prototype._traverseNodes = function (indices, action, parentNode) {
+                if (parentNode === void 0) { parentNode = null; }
+                for (var i = 0; i < indices.length; i++) {
+                    this._traverseNode(indices[i], action, parentNode);
                 }
             };
-            GLTFLoader.prototype._traverseNode = function (nodeNames, index, action, parentNode) {
+            GLTFLoader.prototype._traverseNode = function (index, action, parentNode) {
                 if (parentNode === void 0) { parentNode = null; }
                 var node = this._gltf.nodes[index];
-                if (nodeNames) {
-                    if (nodeNames.indexOf(node.name)) {
-                        // load all children
-                        nodeNames = null;
-                    }
-                    else {
-                        // skip this node tree
-                        return;
-                    }
-                }
-                node.index = index;
-                if (!action(node, parentNode)) {
+                if (!action(node, index, parentNode)) {
                     return;
                 }
                 if (node.children) {
                     for (var i = 0; i < node.children.length; i++) {
-                        this._traverseNode(nodeNames, node.children[i], action, node);
+                        this._traverseNode(node.children[i], action, node);
                     }
                 }
             };
@@ -3004,11 +3030,11 @@ var BABYLON;
             GLTFLoader.prototype._loadBufferAsync = function (index, onSuccess) {
                 var _this = this;
                 var buffer = this._gltf.buffers[index];
-                this._addPendingData(buffer);
+                this.addPendingData(buffer);
                 if (buffer.loadedData) {
                     setTimeout(function () {
                         onSuccess(buffer.loadedData);
-                        _this._removePendingData(buffer);
+                        _this.removePendingData(buffer);
                     });
                 }
                 else if (GLTF2.GLTFUtils.IsBase64(buffer.uri)) {
@@ -3016,20 +3042,20 @@ var BABYLON;
                     buffer.loadedData = new Uint8Array(data);
                     setTimeout(function () {
                         onSuccess(buffer.loadedData);
-                        _this._removePendingData(buffer);
+                        _this.removePendingData(buffer);
                     });
                 }
                 else if (buffer.loadedObservable) {
                     buffer.loadedObservable.add(function (buffer) {
                         onSuccess(buffer.loadedData);
-                        _this._removePendingData(buffer);
+                        _this.removePendingData(buffer);
                     });
                 }
                 else {
                     buffer.loadedObservable = new BABYLON.Observable();
                     buffer.loadedObservable.add(function (buffer) {
                         onSuccess(buffer.loadedData);
-                        _this._removePendingData(buffer);
+                        _this.removePendingData(buffer);
                     });
                     BABYLON.Tools.LoadFile(this._rootUrl + buffer.uri, function (data) {
                         buffer.loadedData = new Uint8Array(data);
@@ -3037,7 +3063,7 @@ var BABYLON;
                         buffer.loadedObservable = null;
                     }, null, null, true, function (request) {
                         _this._errors.push("Failed to load file '" + buffer.uri + "': " + request.statusText + "(" + request.status + ")");
-                        _this._removePendingData(buffer);
+                        _this.removePendingData(buffer);
                     });
                 }
             };
@@ -3084,12 +3110,27 @@ var BABYLON;
                 var byteLength = accessor.count * GLTF2.GLTFUtils.GetByteStrideFromType(accessor);
                 this._loadBufferViewAsync(bufferView, byteOffset, byteLength, accessor.componentType, onSuccess);
             };
-            GLTFLoader.prototype._addPendingData = function (data) {
-                this._pendingCount++;
+            GLTFLoader.prototype.addPendingData = function (data) {
+                if (!this._renderReady) {
+                    this._renderPendingCount++;
+                }
+                this.addLoaderPendingData(data);
+            };
+            GLTFLoader.prototype.removePendingData = function (data) {
+                if (!this._renderReady) {
+                    if (--this._renderPendingCount === 0) {
+                        this._renderReady = true;
+                        this._onRenderReady();
+                    }
+                }
+                this.removeLoaderPendingData(data);
+            };
+            GLTFLoader.prototype.addLoaderPendingData = function (data) {
+                this._loaderPendingCount++;
             };
-            GLTFLoader.prototype._removePendingData = function (data) {
-                if (--this._pendingCount === 0) {
-                    this._onLoaded();
+            GLTFLoader.prototype.removeLoaderPendingData = function (data) {
+                if (--this._loaderPendingCount === 0) {
+                    this._onLoaderComplete();
                 }
             };
             GLTFLoader.prototype._getDefaultMaterial = function () {
@@ -3106,46 +3147,49 @@ var BABYLON;
                 }
                 return this._defaultMaterial;
             };
-            GLTFLoader.prototype._loadMaterial = function (index) {
-                var materials = this._gltf.materials;
-                var material = materials ? materials[index] : null;
-                if (!material) {
-                    BABYLON.Tools.Warn("Material index (" + index + ") does not exist");
-                    return null;
-                }
-                material.babylonMaterial = new BABYLON.PBRMaterial(material.name || "mat" + index, this._babylonScene);
-                material.babylonMaterial.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation;
-                material.babylonMaterial.useScalarInLinearSpace = true;
-                return material;
-            };
-            GLTFLoader.prototype._loadCoreMaterial = function (index) {
-                var material = this._loadMaterial(index);
-                if (!material) {
-                    return null;
-                }
-                this._loadCommonMaterialProperties(material);
+            GLTFLoader.prototype._loadMaterialMetallicRoughnessProperties = function (material) {
                 // Ensure metallic workflow
                 material.babylonMaterial.metallic = 1;
                 material.babylonMaterial.roughness = 1;
                 var properties = material.pbrMetallicRoughness;
-                if (properties) {
-                    material.babylonMaterial.albedoColor = properties.baseColorFactor ? BABYLON.Color3.FromArray(properties.baseColorFactor) : new BABYLON.Color3(1, 1, 1);
-                    material.babylonMaterial.metallic = properties.metallicFactor === undefined ? 1 : properties.metallicFactor;
-                    material.babylonMaterial.roughness = properties.roughnessFactor === undefined ? 1 : properties.roughnessFactor;
-                    if (properties.baseColorTexture) {
-                        material.babylonMaterial.albedoTexture = this._loadTexture(properties.baseColorTexture);
-                        this._loadAlphaProperties(material);
-                    }
-                    if (properties.metallicRoughnessTexture) {
-                        material.babylonMaterial.metallicTexture = this._loadTexture(properties.metallicRoughnessTexture);
-                        material.babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
-                        material.babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
-                        material.babylonMaterial.useRoughnessFromMetallicTextureAlpha = false;
-                    }
+                if (!properties) {
+                    return;
                 }
-                return material.babylonMaterial;
+                material.babylonMaterial.albedoColor = properties.baseColorFactor ? BABYLON.Color3.FromArray(properties.baseColorFactor) : new BABYLON.Color3(1, 1, 1);
+                material.babylonMaterial.metallic = properties.metallicFactor === undefined ? 1 : properties.metallicFactor;
+                material.babylonMaterial.roughness = properties.roughnessFactor === undefined ? 1 : properties.roughnessFactor;
+                if (properties.baseColorTexture) {
+                    material.babylonMaterial.albedoTexture = this.loadTexture(properties.baseColorTexture);
+                    this.loadMaterialAlphaProperties(material);
+                }
+                if (properties.metallicRoughnessTexture) {
+                    material.babylonMaterial.metallicTexture = this.loadTexture(properties.metallicRoughnessTexture);
+                    material.babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
+                    material.babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
+                    material.babylonMaterial.useRoughnessFromMetallicTextureAlpha = false;
+                }
+            };
+            GLTFLoader.prototype.loadMaterial = function (index, assign) {
+                var material = this._gltf.materials[index];
+                material.index = index;
+                if (material.babylonMaterial) {
+                    assign(material.babylonMaterial);
+                    return;
+                }
+                if (GLTF2.GLTFLoaderExtension.LoadMaterial(this, material, assign)) {
+                    return;
+                }
+                this.createPbrMaterial(material);
+                this.loadMaterialBaseProperties(material);
+                this._loadMaterialMetallicRoughnessProperties(material);
+                assign(material.babylonMaterial);
+            };
+            GLTFLoader.prototype.createPbrMaterial = function (material) {
+                material.babylonMaterial = new BABYLON.PBRMaterial(material.name || "mat" + material.index, this._babylonScene);
+                material.babylonMaterial.sideOrientation = BABYLON.Material.CounterClockWiseSideOrientation;
+                material.babylonMaterial.useScalarInLinearSpace = true;
             };
-            GLTFLoader.prototype._loadCommonMaterialProperties = function (material) {
+            GLTFLoader.prototype.loadMaterialBaseProperties = function (material) {
                 material.babylonMaterial.useEmissiveAsIllumination = (material.emissiveFactor || material.emissiveTexture) ? true : false;
                 material.babylonMaterial.emissiveColor = material.emissiveFactor ? BABYLON.Color3.FromArray(material.emissiveFactor) : new BABYLON.Color3(0, 0, 0);
                 if (material.doubleSided) {
@@ -3153,23 +3197,23 @@ var BABYLON;
                     material.babylonMaterial.twoSidedLighting = true;
                 }
                 if (material.normalTexture) {
-                    material.babylonMaterial.bumpTexture = this._loadTexture(material.normalTexture);
+                    material.babylonMaterial.bumpTexture = this.loadTexture(material.normalTexture);
                     if (material.normalTexture.scale !== undefined) {
                         material.babylonMaterial.bumpTexture.level = material.normalTexture.scale;
                     }
                 }
                 if (material.occlusionTexture) {
-                    material.babylonMaterial.ambientTexture = this._loadTexture(material.occlusionTexture);
+                    material.babylonMaterial.ambientTexture = this.loadTexture(material.occlusionTexture);
                     material.babylonMaterial.useAmbientInGrayScale = true;
                     if (material.occlusionTexture.strength !== undefined) {
                         material.babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
                     }
                 }
                 if (material.emissiveTexture) {
-                    material.babylonMaterial.emissiveTexture = this._loadTexture(material.emissiveTexture);
+                    material.babylonMaterial.emissiveTexture = this.loadTexture(material.emissiveTexture);
                 }
             };
-            GLTFLoader.prototype._loadAlphaProperties = function (material) {
+            GLTFLoader.prototype.loadMaterialAlphaProperties = function (material) {
                 var alphaMode = material.alphaMode || "OPAQUE";
                 switch (alphaMode) {
                     case "OPAQUE":
@@ -3178,18 +3222,17 @@ var BABYLON;
                     case "MASK":
                         material.babylonMaterial.albedoTexture.hasAlpha = true;
                         material.babylonMaterial.useAlphaFromAlbedoTexture = false;
-                        material.babylonMaterial.alphaMode = BABYLON.Engine.ALPHA_DISABLE;
                         break;
                     case "BLEND":
                         material.babylonMaterial.albedoTexture.hasAlpha = true;
                         material.babylonMaterial.useAlphaFromAlbedoTexture = true;
-                        material.babylonMaterial.alphaMode = BABYLON.Engine.ALPHA_COMBINE;
                         break;
                     default:
-                        BABYLON.Tools.Error("Invalid alpha mode '" + material.alphaMode + "'");
+                        BABYLON.Tools.Warn("Invalid alpha mode '" + material.alphaMode + "'");
+                        break;
                 }
             };
-            GLTFLoader.prototype._loadTexture = function (textureInfo) {
+            GLTFLoader.prototype.loadTexture = function (textureInfo) {
                 var _this = this;
                 var texture = this._gltf.textures[textureInfo.index];
                 var texCoord = textureInfo.texCoord || 0;
@@ -3232,12 +3275,12 @@ var BABYLON;
                 var sampler = (texture.sampler === undefined ? {} : this._gltf.samplers[texture.sampler]);
                 var noMipMaps = (sampler.minFilter === GLTF2.ETextureMinFilter.NEAREST || sampler.minFilter === GLTF2.ETextureMinFilter.LINEAR);
                 var samplingMode = GLTF2.GLTFUtils.GetTextureFilterMode(sampler.minFilter);
-                this._addPendingData(texture);
+                this.addPendingData(texture);
                 var babylonTexture = new BABYLON.Texture(url, this._babylonScene, noMipMaps, false, samplingMode, function () {
-                    _this._removePendingData(texture);
+                    _this.removePendingData(texture);
                 }, function () {
                     _this._errors.push("Failed to load texture '" + source.uri + "'");
-                    _this._removePendingData(texture);
+                    _this.removePendingData(texture);
                 });
                 babylonTexture.coordinatesIndex = texCoord;
                 babylonTexture.wrapU = GLTF2.GLTFUtils.GetWrapMode(sampler.wrapS);
@@ -3358,42 +3401,39 @@ var BABYLON;
     var GLTF2;
     (function (GLTF2) {
         var GLTFLoaderExtension = (function () {
-            function GLTFLoaderExtension(name) {
+            function GLTFLoaderExtension() {
                 this.enabled = true;
-                this._name = name;
             }
-            Object.defineProperty(GLTFLoaderExtension.prototype, "name", {
-                get: function () {
-                    return this._name;
-                },
-                enumerable: true,
-                configurable: true
-            });
-            GLTFLoaderExtension.prototype.loadMaterial = function (index) { return null; };
-            // ---------
-            // Utilities
-            // ---------
-            GLTFLoaderExtension.LoadMaterial = function (index) {
-                for (var extensionName in GLTF2.GLTFLoader.Extensions) {
-                    var extension = GLTF2.GLTFLoader.Extensions[extensionName];
-                    if (extension.enabled) {
-                        var babylonMaterial = extension.loadMaterial(index);
-                        if (babylonMaterial) {
-                            return babylonMaterial;
-                        }
+            GLTFLoaderExtension.prototype.loadMaterial = function (loader, material, assign) { return false; };
+            GLTFLoaderExtension.LoadMaterial = function (loader, material, assign) {
+                return this._ApplyExtensions(function (extension) { return extension.loadMaterial(loader, material, assign); });
+            };
+            GLTFLoaderExtension._ApplyExtensions = function (action) {
+                var extensions = GLTFLoaderExtension._Extensions;
+                if (!extensions) {
+                    return;
+                }
+                for (var i = 0; i < extensions.length; i++) {
+                    var extension = extensions[i];
+                    if (extension.enabled && action(extension)) {
+                        return true;
                     }
                 }
-                return GLTF2.GLTFLoader.LoadCoreMaterial(index);
+                return false;
             };
             return GLTFLoaderExtension;
         }());
+        //
+        // Utilities
+        //
+        GLTFLoaderExtension._Extensions = [];
         GLTF2.GLTFLoaderExtension = GLTFLoaderExtension;
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
 //# sourceMappingURL=babylon.glTFLoaderExtension.js.map
 
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+/// <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; }) ||
@@ -3408,43 +3448,122 @@ var BABYLON;
 (function (BABYLON) {
     var GLTF2;
     (function (GLTF2) {
-        var GLTFMaterialsPbrSpecularGlossinessExtension = (function (_super) {
-            __extends(GLTFMaterialsPbrSpecularGlossinessExtension, _super);
-            function GLTFMaterialsPbrSpecularGlossinessExtension() {
-                return _super.call(this, "KHR_materials_pbrSpecularGlossiness") || this;
-            }
-            GLTFMaterialsPbrSpecularGlossinessExtension.prototype.loadMaterial = function (index) {
-                var material = GLTF2.GLTFLoader.LoadMaterial(index);
-                if (!material || !material.extensions)
-                    return null;
-                var properties = material.extensions[this.name];
-                if (!properties)
-                    return null;
-                GLTF2.GLTFLoader.LoadCommonMaterialProperties(material);
-                //
-                // Load Factors
-                //
-                material.babylonMaterial.albedoColor = properties.diffuseFactor ? BABYLON.Color3.FromArray(properties.diffuseFactor) : new BABYLON.Color3(1, 1, 1);
-                material.babylonMaterial.reflectivityColor = properties.specularFactor ? BABYLON.Color3.FromArray(properties.specularFactor) : new BABYLON.Color3(1, 1, 1);
-                material.babylonMaterial.microSurface = properties.glossinessFactor === undefined ? 1 : properties.glossinessFactor;
-                //
-                // Load Textures
-                //
-                if (properties.diffuseTexture) {
-                    material.babylonMaterial.albedoTexture = GLTF2.GLTFLoader.LoadTexture(properties.diffuseTexture);
-                    GLTF2.GLTFLoader.LoadAlphaProperties(material);
-                }
-                if (properties.specularGlossinessTexture) {
-                    material.babylonMaterial.reflectivityTexture = GLTF2.GLTFLoader.LoadTexture(properties.specularGlossinessTexture);
-                    material.babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
-                }
-                return material.babylonMaterial;
-            };
-            return GLTFMaterialsPbrSpecularGlossinessExtension;
-        }(GLTF2.GLTFLoaderExtension));
-        GLTF2.GLTFMaterialsPbrSpecularGlossinessExtension = GLTFMaterialsPbrSpecularGlossinessExtension;
-        GLTF2.GLTFLoader.RegisterExtension(new GLTFMaterialsPbrSpecularGlossinessExtension());
+        var Extensions;
+        (function (Extensions) {
+            var MSFTLOD = (function (_super) {
+                __extends(MSFTLOD, _super);
+                function MSFTLOD() {
+                    return _super !== null && _super.apply(this, arguments) || this;
+                }
+                Object.defineProperty(MSFTLOD.prototype, "name", {
+                    get: function () {
+                        return "MSFT_lod";
+                    },
+                    enumerable: true,
+                    configurable: true
+                });
+                MSFTLOD.prototype.loadMaterial = function (loader, material, assign) {
+                    if (!material.extensions) {
+                        return false;
+                    }
+                    var properties = material.extensions[this.name];
+                    if (!properties) {
+                        return false;
+                    }
+                    // Clear out the extension so that it won't get loaded again.
+                    material.extensions[this.name] = undefined;
+                    // Tell the loader not to clear its state until the highest LOD is loaded.
+                    loader.addLoaderPendingData(material);
+                    // Start with the lowest quality LOD.
+                    var materialLODs = [material.index].concat(properties.ids);
+                    this.loadMaterialLOD(loader, material, materialLODs, materialLODs.length - 1, assign);
+                    return true;
+                };
+                MSFTLOD.prototype.loadMaterialLOD = function (loader, material, materialLODs, lod, assign) {
+                    var _this = this;
+                    loader.loadMaterial(materialLODs[lod], function (babylonMaterial) {
+                        babylonMaterial.name += ".LOD" + lod;
+                        assign(babylonMaterial);
+                        // Loading is complete if this is the highest quality LOD.
+                        if (lod === 0) {
+                            loader.removeLoaderPendingData(material);
+                            return;
+                        }
+                        // Load the next LOD when all of the textures are loaded.
+                        BABYLON.BaseTexture.WhenAllReady(babylonMaterial.getActiveTextures(), function () {
+                            _this.loadMaterialLOD(loader, material, materialLODs, lod - 1, assign);
+                        });
+                    });
+                };
+                return MSFTLOD;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.MSFTLOD = MSFTLOD;
+            GLTF2.GLTFLoader.RegisterExtension(new MSFTLOD());
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=MSFT_lod.js.map
+
+/// <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 GLTF2;
+    (function (GLTF2) {
+        var Extensions;
+        (function (Extensions) {
+            var KHRMaterialsPbrSpecularGlossiness = (function (_super) {
+                __extends(KHRMaterialsPbrSpecularGlossiness, _super);
+                function KHRMaterialsPbrSpecularGlossiness() {
+                    return _super !== null && _super.apply(this, arguments) || this;
+                }
+                Object.defineProperty(KHRMaterialsPbrSpecularGlossiness.prototype, "name", {
+                    get: function () {
+                        return "KHR_materials_pbrSpecularGlossiness";
+                    },
+                    enumerable: true,
+                    configurable: true
+                });
+                KHRMaterialsPbrSpecularGlossiness.prototype.loadMaterial = function (loader, material, assign) {
+                    if (!material.extensions) {
+                        return false;
+                    }
+                    var properties = material.extensions[this.name];
+                    if (!properties) {
+                        return false;
+                    }
+                    loader.createPbrMaterial(material);
+                    loader.loadMaterialBaseProperties(material);
+                    material.babylonMaterial.albedoColor = properties.diffuseFactor ? BABYLON.Color3.FromArray(properties.diffuseFactor) : new BABYLON.Color3(1, 1, 1);
+                    material.babylonMaterial.reflectivityColor = properties.specularFactor ? BABYLON.Color3.FromArray(properties.specularFactor) : new BABYLON.Color3(1, 1, 1);
+                    material.babylonMaterial.microSurface = properties.glossinessFactor === undefined ? 1 : properties.glossinessFactor;
+                    if (properties.diffuseTexture) {
+                        material.babylonMaterial.albedoTexture = loader.loadTexture(properties.diffuseTexture);
+                        loader.loadMaterialAlphaProperties(material);
+                    }
+                    if (properties.specularGlossinessTexture) {
+                        material.babylonMaterial.reflectivityTexture = loader.loadTexture(properties.specularGlossinessTexture);
+                        material.babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
+                    }
+                    assign(material.babylonMaterial);
+                    return true;
+                };
+                return KHRMaterialsPbrSpecularGlossiness;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.KHRMaterialsPbrSpecularGlossiness = KHRMaterialsPbrSpecularGlossiness;
+            GLTF2.GLTFLoader.RegisterExtension(new KHRMaterialsPbrSpecularGlossiness());
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
-//# sourceMappingURL=babylon.glTFMaterialsPbrSpecularGlossinessExtension.js.map
+//# sourceMappingURL=KHR_materials_pbrSpecularGlossiness.js.map

Різницю між файлами не показано, бо вона завелика
+ 2 - 7
dist/preview release/loaders/babylon.glTFFileLoader.min.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 5
dist/preview release/loaders/babylon.objFileLoader.min.js


+ 1 - 0
dist/preview release/materialsLibrary/babylon.cellMaterial.d.ts

@@ -20,6 +20,7 @@ declare module BABYLON {
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
+        getActiveTextures(): BaseTexture[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): CellMaterial;
         serialize(): any;

+ 7 - 0
dist/preview release/materialsLibrary/babylon.cellMaterial.js

@@ -220,6 +220,13 @@ var BABYLON;
             }
             return results;
         };
+        CellMaterial.prototype.getActiveTextures = function () {
+            var activeTextures = _super.prototype.getActiveTextures.call(this);
+            if (this._diffuseTexture) {
+                activeTextures.push(this._diffuseTexture);
+            }
+            return activeTextures;
+        };
         CellMaterial.prototype.dispose = function (forceDisposeEffect) {
             if (this._diffuseTexture) {
                 this._diffuseTexture.dispose();

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/materialsLibrary/babylon.cellMaterial.min.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


+ 1 - 0
dist/preview release/materialsLibrary/babylon.fireMaterial.d.ts

@@ -19,6 +19,7 @@ declare module BABYLON {
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
+        getActiveTextures(): BaseTexture[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): FireMaterial;
         serialize(): any;

+ 13 - 0
dist/preview release/materialsLibrary/babylon.fireMaterial.js

@@ -209,6 +209,19 @@ var BABYLON;
             }
             return results;
         };
+        FireMaterial.prototype.getActiveTextures = function () {
+            var activeTextures = _super.prototype.getActiveTextures.call(this);
+            if (this._diffuseTexture) {
+                activeTextures.push(this._diffuseTexture);
+            }
+            if (this._distortionTexture) {
+                activeTextures.push(this._distortionTexture);
+            }
+            if (this._opacityTexture) {
+                activeTextures.push(this._opacityTexture);
+            }
+            return activeTextures;
+        };
         FireMaterial.prototype.dispose = function (forceDisposeEffect) {
             if (this._diffuseTexture) {
                 this._diffuseTexture.dispose();

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/materialsLibrary/babylon.fireMaterial.min.js


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

@@ -33,6 +33,7 @@ declare module BABYLON {
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
+        getActiveTextures(): BaseTexture[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): FurMaterial;
         serialize(): any;

+ 10 - 0
dist/preview release/materialsLibrary/babylon.furMaterial.js

@@ -285,6 +285,16 @@ var BABYLON;
             }
             return results;
         };
+        FurMaterial.prototype.getActiveTextures = function () {
+            var activeTextures = _super.prototype.getActiveTextures.call(this);
+            if (this._diffuseTexture) {
+                activeTextures.push(this._diffuseTexture);
+            }
+            if (this._heightTexture) {
+                activeTextures.push(this._heightTexture);
+            }
+            return activeTextures;
+        };
         FurMaterial.prototype.dispose = function (forceDisposeEffect) {
             if (this.diffuseTexture) {
                 this.diffuseTexture.dispose();

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/materialsLibrary/babylon.furMaterial.min.js


+ 1 - 0
dist/preview release/materialsLibrary/babylon.lavaMaterial.d.ts

@@ -25,6 +25,7 @@ declare module BABYLON {
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
+        getActiveTextures(): BaseTexture[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): LavaMaterial;
         serialize(): any;

+ 7 - 0
dist/preview release/materialsLibrary/babylon.lavaMaterial.js

@@ -271,6 +271,13 @@ var BABYLON;
             }
             return results;
         };
+        LavaMaterial.prototype.getActiveTextures = function () {
+            var activeTextures = _super.prototype.getActiveTextures.call(this);
+            if (this._diffuseTexture) {
+                activeTextures.push(this._diffuseTexture);
+            }
+            return activeTextures;
+        };
         LavaMaterial.prototype.dispose = function (forceDisposeEffect) {
             if (this.diffuseTexture) {
                 this.diffuseTexture.dispose();

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/materialsLibrary/babylon.lavaMaterial.min.js


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

@@ -18,6 +18,7 @@ declare module BABYLON {
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
+        getActiveTextures(): BaseTexture[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): NormalMaterial;
         serialize(): any;

+ 7 - 0
dist/preview release/materialsLibrary/babylon.normalMaterial.js

@@ -247,6 +247,13 @@ var BABYLON;
             }
             return results;
         };
+        NormalMaterial.prototype.getActiveTextures = function () {
+            var activeTextures = _super.prototype.getActiveTextures.call(this);
+            if (this._diffuseTexture) {
+                activeTextures.push(this._diffuseTexture);
+            }
+            return activeTextures;
+        };
         NormalMaterial.prototype.dispose = function (forceDisposeEffect) {
             if (this.diffuseTexture) {
                 this.diffuseTexture.dispose();

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/materialsLibrary/babylon.normalMaterial.min.js


+ 1 - 0
dist/preview release/materialsLibrary/babylon.simpleMaterial.d.ts

@@ -18,6 +18,7 @@ declare module BABYLON {
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
+        getActiveTextures(): BaseTexture[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): SimpleMaterial;
         serialize(): any;

+ 7 - 0
dist/preview release/materialsLibrary/babylon.simpleMaterial.js

@@ -214,6 +214,13 @@ var BABYLON;
             }
             return results;
         };
+        SimpleMaterial.prototype.getActiveTextures = function () {
+            var activeTextures = _super.prototype.getActiveTextures.call(this);
+            if (this._diffuseTexture) {
+                activeTextures.push(this._diffuseTexture);
+            }
+            return activeTextures;
+        };
         SimpleMaterial.prototype.dispose = function (forceDisposeEffect) {
             if (this._diffuseTexture) {
                 this._diffuseTexture.dispose();

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/materialsLibrary/babylon.simpleMaterial.min.js


+ 1 - 0
dist/preview release/materialsLibrary/babylon.terrainMaterial.d.ts

@@ -31,6 +31,7 @@ declare module BABYLON {
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
+        getActiveTextures(): BaseTexture[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): TerrainMaterial;
         serialize(): any;

+ 25 - 0
dist/preview release/materialsLibrary/babylon.terrainMaterial.js

@@ -250,6 +250,31 @@ var BABYLON;
             }
             return results;
         };
+        TerrainMaterial.prototype.getActiveTextures = function () {
+            var activeTextures = _super.prototype.getActiveTextures.call(this);
+            if (this._mixTexture) {
+                activeTextures.push(this._mixTexture);
+            }
+            if (this._diffuseTexture1) {
+                activeTextures.push(this._diffuseTexture1);
+            }
+            if (this._diffuseTexture2) {
+                activeTextures.push(this._diffuseTexture2);
+            }
+            if (this._diffuseTexture3) {
+                activeTextures.push(this._diffuseTexture3);
+            }
+            if (this._bumpTexture1) {
+                activeTextures.push(this._bumpTexture1);
+            }
+            if (this._bumpTexture2) {
+                activeTextures.push(this._bumpTexture2);
+            }
+            if (this._bumpTexture3) {
+                activeTextures.push(this._bumpTexture3);
+            }
+            return activeTextures;
+        };
         TerrainMaterial.prototype.dispose = function (forceDisposeEffect) {
             if (this.mixTexture) {
                 this.mixTexture.dispose();

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/materialsLibrary/babylon.terrainMaterial.min.js


+ 1 - 0
dist/preview release/materialsLibrary/babylon.triPlanarMaterial.d.ts

@@ -31,6 +31,7 @@ declare module BABYLON {
         isReadyForSubMesh(mesh: AbstractMesh, subMesh: SubMesh, useInstances?: boolean): boolean;
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         getAnimatables(): IAnimatable[];
+        getActiveTextures(): BaseTexture[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): TriPlanarMaterial;
         serialize(): any;

+ 22 - 0
dist/preview release/materialsLibrary/babylon.triPlanarMaterial.js

@@ -251,6 +251,28 @@ var BABYLON;
             }
             return results;
         };
+        TriPlanarMaterial.prototype.getActiveTextures = function () {
+            var activeTextures = _super.prototype.getActiveTextures.call(this);
+            if (this._diffuseTextureX) {
+                activeTextures.push(this._diffuseTextureX);
+            }
+            if (this._diffuseTextureY) {
+                activeTextures.push(this._diffuseTextureY);
+            }
+            if (this._diffuseTextureZ) {
+                activeTextures.push(this._diffuseTextureZ);
+            }
+            if (this._normalTextureX) {
+                activeTextures.push(this._normalTextureX);
+            }
+            if (this._normalTextureY) {
+                activeTextures.push(this._normalTextureY);
+            }
+            if (this._normalTextureZ) {
+                activeTextures.push(this._normalTextureZ);
+            }
+            return activeTextures;
+        };
         TriPlanarMaterial.prototype.dispose = function (forceDisposeEffect) {
             if (this.mixTexture) {
                 this.mixTexture.dispose();

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/materialsLibrary/babylon.triPlanarMaterial.min.js


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

@@ -92,6 +92,7 @@ declare module BABYLON {
         bindForSubMesh(world: Matrix, mesh: Mesh, subMesh: SubMesh): void;
         private _createRenderTargets(scene, renderTargetSize);
         getAnimatables(): IAnimatable[];
+        getActiveTextures(): BaseTexture[];
         dispose(forceDisposeEffect?: boolean): void;
         clone(name: string): WaterMaterial;
         serialize(): any;

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

@@ -444,6 +444,13 @@ var BABYLON;
             }
             return results;
         };
+        WaterMaterial.prototype.getActiveTextures = function () {
+            var activeTextures = _super.prototype.getActiveTextures.call(this);
+            if (this._bumpTexture) {
+                activeTextures.push(this._bumpTexture);
+            }
+            return activeTextures;
+        };
         WaterMaterial.prototype.dispose = function (forceDisposeEffect) {
             if (this.bumpTexture) {
                 this.bumpTexture.dispose();

Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


Різницю між файлами не показано, бо вона завелика
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


+ 3 - 1
dist/preview release/what's new.md

@@ -28,6 +28,7 @@
  - New blur mode for mirrors. [Demo](https://www.babylonjs-playground.com/#9I6NX1) ([deltakosh](https://github.com/deltakosh)) 
 
 ### Updates
+- new `Texture.readPixels()` function to read texture content ([deltakosh](https://github.com/deltakosh))
 - New helpers to use ExtrudePolygon. [Demo](http://www.babylonjs-playground.com/#RNCYVM#10) ([Cubees](https://github.com/Cubees))
 - PostProcess can now use alpha blending and share outputs ([deltakosh](https://github.com/deltakosh))
 - Added `ArcRotateCamera.panningInertia` to decouple inertia from panning inertia ([deltakosh](https://github.com/deltakosh))
@@ -72,7 +73,8 @@
 - Fixed an issue with Mesh.attachToBone when a mesh is moving and an animation is changed ([abow](https://github.com/abow))
 - Fixed an issue withaspect ratio when using CreateScreenshot ([deltakosh](https://github.com/deltakosh))
 - Fixed SPS particle initial status when used as updatable with a `positionFunction` in `addShape()` ([jerome](https://github.com/jbousquie))  
-- Fixed SPS particle access start index when used with `setParticles(start, end)` ([jerome](https://github.com/jbousquie))  
+- Fixed SPS particle access `start` index when used with `setParticles(start, end)` ([jerome](https://github.com/jbousquie))  
+- Fixed SPS billboard mode when used with a parented camera ([jerome](https://github.com/jbousquie)) 
 
 ### API Documentation
 - File `abstractMesh.ts` documented ([jerome](https://github.com/jbousquie))  

+ 3 - 0
inspector/src/Inspector.ts

@@ -40,6 +40,9 @@ module INSPECTOR {
             colorBot?: string
         }) {
 
+            //Load properties of GUI objects now as BABYLON.GUI has to be declared before 
+            loadGUIProperties();
+
             //get Tabbar initialTab
             this._initialTab = initialTab;
 

+ 135 - 0
inspector/src/adapters/GUIAdapter.ts

@@ -0,0 +1,135 @@
+module INSPECTOR {
+    
+    export class GUIAdapter 
+        extends Adapter 
+        implements IToolVisible {
+
+        constructor(obj: BABYLON.GUI.Control) {
+            super(obj);
+        }
+
+        /** Returns the name displayed in the tree */
+        public id(): string {
+            let str = '';
+            if (this._obj.name) {
+                str = this._obj.name;
+            } // otherwise nothing displayed        
+            return str;
+        }
+
+        /** Returns the type of this object - displayed in the tree */
+        public type(): string {
+            return Helpers.GET_TYPE(this._obj);
+        }
+
+        /** Returns the list of properties to be displayed for this adapter */
+        public getProperties(): Array<PropertyLine> {
+            let propertiesLines: Array<PropertyLine> = [];
+
+            for (let dirty of PROPERTIES['Control'].properties) {
+                let infos = new Property(dirty, this._obj);
+                propertiesLines.push(new PropertyLine(infos));
+            }
+
+            if(this._obj instanceof BABYLON.GUI.Button){
+                for (let dirty of PROPERTIES['Button'].properties) {
+                    let infos = new Property(dirty, this._obj);
+                    propertiesLines.push(new PropertyLine(infos));
+                }
+            }
+
+            if(this._obj instanceof BABYLON.GUI.ColorPicker){
+                for (let dirty of PROPERTIES['ColorPicker'].properties) {
+                    let infos = new Property(dirty, this._obj);
+                    propertiesLines.push(new PropertyLine(infos));
+                }
+            }
+
+            if(this._obj instanceof BABYLON.GUI.Checkbox){
+                for (let dirty of PROPERTIES['Checkbox'].properties) {
+                    let infos = new Property(dirty, this._obj);
+                    propertiesLines.push(new PropertyLine(infos));
+                }
+            }
+
+            if(this._obj instanceof BABYLON.GUI.Ellipse){
+                for (let dirty of PROPERTIES['Ellipse'].properties) {
+                    let infos = new Property(dirty, this._obj);
+                    propertiesLines.push(new PropertyLine(infos));
+                }
+            }
+
+            if(this._obj instanceof BABYLON.GUI.Image){
+                for (let dirty of PROPERTIES['Image'].properties) {
+                    let infos = new Property(dirty, this._obj);
+                    propertiesLines.push(new PropertyLine(infos));
+                }
+            }
+
+            if(this._obj instanceof BABYLON.GUI.Line){
+                for (let dirty of PROPERTIES['Line'].properties) {
+                    let infos = new Property(dirty, this._obj);
+                    propertiesLines.push(new PropertyLine(infos));
+                }
+            }
+
+            if(this._obj instanceof BABYLON.GUI.RadioButton){
+                for (let dirty of PROPERTIES['RadioButton'].properties) {
+                    let infos = new Property(dirty, this._obj);
+                    propertiesLines.push(new PropertyLine(infos));
+                }
+            }
+
+            if(this._obj instanceof BABYLON.GUI.Rectangle){
+                for (let dirty of PROPERTIES['Rectangle'].properties) {
+                    let infos = new Property(dirty, this._obj);
+                    propertiesLines.push(new PropertyLine(infos));
+                }
+            }
+
+            if(this._obj instanceof BABYLON.GUI.Slider){
+                for (let dirty of PROPERTIES['Slider'].properties) {
+                    let infos = new Property(dirty, this._obj);
+                    propertiesLines.push(new PropertyLine(infos));
+                }
+            }
+
+            if(this._obj instanceof BABYLON.GUI.StackPanel){
+                for (let dirty of PROPERTIES['StackPanel'].properties) {
+                    let infos = new Property(dirty, this._obj);
+                    propertiesLines.push(new PropertyLine(infos));
+                }
+            }
+
+            if(this._obj instanceof BABYLON.GUI.TextBlock){
+                for (let dirty of PROPERTIES['TextBlock'].properties) {
+                    let infos = new Property(dirty, this._obj);
+                    propertiesLines.push(new PropertyLine(infos));
+                }
+            }
+
+            if(this._obj instanceof BABYLON.GUI.Container){
+                for (let dirty of PROPERTIES['Container'].properties) {
+                    let infos = new Property(dirty, this._obj);
+                    propertiesLines.push(new PropertyLine(infos));
+                }
+            }
+
+            return propertiesLines;
+        }
+
+        public getTools(): Array<AbstractTreeTool> {
+            let tools = [];
+            tools.push(new Checkbox(this));
+            return tools;
+        }
+
+        public setVisible(b: boolean){
+            (this._obj as BABYLON.GUI.Control).isVisible = b;
+        }
+
+        public isVisible(): boolean{
+            return (this._obj as BABYLON.GUI.Control).isVisible;
+        }
+    }
+}

+ 1 - 0
inspector/src/lib.d.ts

@@ -1,5 +1,6 @@
 /// <reference path="../../dist/preview release/babylon.d.ts"/>
 /// <reference path="babylon.canvas2D.d.ts"/>
+/// <reference path="../../dist/preview release/gui/babylon.gui.d.ts"/>
 
 interface ISplit {
     setSizes(sizes:Array<number>);

+ 1 - 1
inspector/src/properties.ts

@@ -1,6 +1,6 @@
 module INSPECTOR {
 
-    export const PROPERTIES = {
+    export var PROPERTIES = {
         /** Format the given object : 
          * If a format function exists, returns the result of this function.
          * If this function doesn't exists, return the object type instead */

+ 116 - 0
inspector/src/properties_gui.ts

@@ -0,0 +1,116 @@
+module INSPECTOR {
+    /**
+     * Function that add gui objects properties to the variable PROPERTIES
+     */
+    export function loadGUIProperties(){
+        let PROPERTIES_GUI = {
+            'ValueAndUnit': {
+                type: BABYLON.GUI.ValueAndUnit,
+                properties: ['_value', 'unit'],
+                format: (valueAndUnit: BABYLON.GUI.ValueAndUnit) => 
+                    { return valueAndUnit }
+            },
+            'Control': {
+                type: BABYLON.GUI.Control,
+                properties: [
+                    '_alpha',
+                    '_fontFamily',
+                    '_color',
+                    '_scaleX',
+                    '_scaleY',
+                    '_rotation',
+                    '_currentMeasure',
+                    '_width',
+                    '_height',
+                    '_left',
+                    '_top',
+                    '_linkedMesh',
+                    'isHitTestVisible',
+                    'isPointerBlocker',
+                ],
+                format: (control: BABYLON.GUI.Control) => { return control.name }
+            },
+            'Button': {
+                type: BABYLON.GUI.Button,
+                properties: [],
+                format: (button: BABYLON.GUI.Button) => { return button.name }
+            },
+            'ColorPicker': {
+                type: BABYLON.GUI.ColorPicker,
+                properties: ['_value'],
+                format: (colorPicker: BABYLON.GUI.ColorPicker) => { return colorPicker.name }
+            },
+            'Checkbox': {
+                type: BABYLON.GUI.Checkbox,
+                properties: ['_isChecked', '_background'],
+                format: (checkbox: BABYLON.GUI.Checkbox) => { return checkbox.name }
+            },
+            'Ellipse': {
+                type: BABYLON.GUI.Ellipse,
+                properties: ['_thickness'],
+                format: (ellipse: BABYLON.GUI.Ellipse) => { return ellipse.name }
+            },
+            'Image': {
+                type: BABYLON.GUI.Image,
+                properties: [
+                    '_imageWidth', 
+                    '_imageHeight',
+                    '_loaded',
+                    '_source',
+                ],
+                format: (image: BABYLON.GUI.Image) => { return image.name }
+            },
+            'Line': {
+                type: BABYLON.GUI.Line,
+                properties: ['_lineWidth',
+                    '_background',
+                    '_x1',
+                    '_y1',
+                    '_x2',
+                    '_y2',
+                ],
+                format: (line: BABYLON.GUI.Line) => { return line.name }
+            },
+            'RadioButton': {
+                type: BABYLON.GUI.RadioButton,
+                properties: ['_isChecked', '_background'],
+                format: (radioButton: BABYLON.GUI.RadioButton) => { return radioButton.name }
+            },
+            'Rectangle': {
+                type: BABYLON.GUI.Rectangle,
+                properties: ['_thickness', '_cornerRadius'],
+                format: (rectangle: BABYLON.GUI.Rectangle) => { return rectangle.name }
+            },
+            'Slider': {
+                type: BABYLON.GUI.Slider,
+                properties: [
+                    '_minimum',
+                    '_maximum',
+                    '_value',
+                    '_background',
+                    '_borderColor',
+                ],
+                format: (slider: BABYLON.GUI.Slider) => { return slider.name }
+            },
+            'StackPanel': {
+                type: BABYLON.GUI.StackPanel,
+                properties: ['_isVertical'],
+                format: (stackPanel: BABYLON.GUI.StackPanel) => { return stackPanel.name }
+            },
+            'TextBlock': {
+                type: BABYLON.GUI.TextBlock,
+                properties: ['_text', '_textWrapping'],
+                format: (textBlock: BABYLON.GUI.TextBlock) => { return textBlock.name }
+            },
+            'Container': {
+                type: BABYLON.GUI.Container,
+                properties: ['_background'],
+                format: (container: BABYLON.GUI.Container) => { return container.name }
+            },
+        }
+
+        for (let prop in PROPERTIES_GUI) {
+            PROPERTIES[prop] = PROPERTIES_GUI[prop];
+        }
+    } 
+}

+ 42 - 0
inspector/src/tabs/GUITab.ts

@@ -0,0 +1,42 @@
+module INSPECTOR{
+    
+    export class GUITab extends PropertyTab {
+                
+        constructor(tabbar:TabBar, inspector:Inspector) {
+            super(tabbar, 'GUI', inspector); 
+        }
+
+        /* Overrides super */
+        protected _getTree() : Array<TreeItem> {
+            let arr = [];
+
+            // Recursive method building the tree panel
+            let createNode = (obj: BABYLON.GUI.Control) => {
+                let descendants = (obj as BABYLON.GUI.Container).children;
+
+                if (descendants && descendants.length > 0) {
+                    let node = new TreeItem(this, new GUIAdapter(obj));
+                    for (let child of descendants) {     
+                        let n = createNode(child);
+                        node.add(n); 
+                    }
+                    node.update();
+                    return node;
+                } else {
+                    return new TreeItem(this, new GUIAdapter(obj));
+                }
+            };
+            
+            // get all textures from the first scene
+            let instances = this._inspector.scene;
+            for (let tex of instances.textures) {
+                //only get GUI's textures
+                if (tex instanceof BABYLON.GUI.AdvancedDynamicTexture) {
+                    let node = createNode(tex._rootContainer);
+                    arr.push(node);
+                }
+            }
+            return arr;
+        }
+    }
+}

+ 1 - 0
inspector/src/tabs/TabBar.ts

@@ -33,6 +33,7 @@ module INSPECTOR {
             this._tabs.push(new ShaderTab(this, this._inspector));
             this._tabs.push(new LightTab(this, this._inspector));
             this._tabs.push(new MaterialTab(this, this._inspector));
+            this._tabs.push(new GUITab(this, this._inspector));
 
             this._tabs.push(new CameraTab(this, this._inspector));
             this._tabs.push(new SoundTab(this, this._inspector));

+ 58 - 0
inspector/test/index.js

@@ -213,6 +213,64 @@ var Test = (function () {
             cubes.push(b);
         }
 
+        // gui
+        var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
+
+        var picker = new BABYLON.GUI.ColorPicker();
+        picker.height = "150px";
+        picker.width = "150px";
+        picker.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
+
+        var checkbox = new BABYLON.GUI.Checkbox();
+        checkbox.width = "20px";
+        checkbox.height = "20px";
+
+        var slider = new BABYLON.GUI.Slider();
+        slider.minimum = 0;
+        slider.maximum = 2 * Math.PI;
+        slider.value = 0;
+        slider.height = "20px";
+        slider.width = "200px";
+
+        var line = new BABYLON.GUI.Line();
+        line.x1 = 10;
+        line.y1 = 10;
+        line.x2 = 1000;
+        line.y2 = 500;
+
+        var panel = new BABYLON.GUI.StackPanel();    
+
+        var button = BABYLON.GUI.Button.CreateSimpleButton("but", "Click Me");
+        button.width = 0.2;
+        button.height = "40px";
+        button.color = "white";
+        button.background = "green";
+        panel.addControl(button);     
+
+        var button2 = BABYLON.GUI.Button.CreateSimpleButton("but2", "Click Me also!");
+        button2.width = 0.2;
+        button2.height = "40px";
+        button2.color = "white";
+        button2.background = "green";
+        panel.addControl(button2);     
+
+        var ellipse1 = new BABYLON.GUI.Ellipse();
+        ellipse1.width = "100px"
+        ellipse1.height = "100px";
+        ellipse1.color = "Orange";
+        ellipse1.thickness = 4;
+        ellipse1.background = "green";
+
+
+        advancedTexture.addControl(ellipse1);    
+        advancedTexture.addControl(panel);   
+        advancedTexture.addControl(picker);    
+        advancedTexture.addControl(checkbox);    
+        advancedTexture.addControl(slider);    
+        advancedTexture.addControl(line);    
+        advancedTexture.addControl(checkbox);    
+
+
         this.scene = scene;
     };
     return Test;

+ 5 - 2
loaders/src/OBJ/babylon.objFileLoader.ts

@@ -867,6 +867,9 @@ module BABYLON {
         }
 
     }
-    //Add this loader into the register plugin
-    BABYLON.SceneLoader.RegisterPlugin(new OBJFileLoader());
+
+    if (BABYLON.SceneLoader) {
+        //Add this loader into the register plugin
+        BABYLON.SceneLoader.RegisterPlugin(new OBJFileLoader());
+    }
 }

+ 3 - 1
loaders/src/STL/babylon.stlFileLoader.ts

@@ -191,5 +191,7 @@ module BABYLON {
         }
     }
 
-    BABYLON.SceneLoader.RegisterPlugin(new STLFileLoader());
+    if (BABYLON.SceneLoader) {
+        BABYLON.SceneLoader.RegisterPlugin(new STLFileLoader());
+    }
 }

+ 1 - 1
loaders/src/glTF/1.0/babylon.glTFLoader.ts

@@ -1731,5 +1731,5 @@ module BABYLON.GLTF1 {
         }
     };
 
-    BABYLON.GLTFFileLoader.GLTFLoaderV1 = new GLTFLoader();
+    BABYLON.GLTFFileLoader.CreateGLTFLoaderV1 = () => new GLTFLoader();
 }

+ 54 - 0
loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts

@@ -0,0 +1,54 @@
+/// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GLTF2.Extensions {
+    interface IKHRMaterialsPbrSpecularGlossiness {
+        diffuseFactor: number[];
+        diffuseTexture: IGLTFTextureInfo;
+        specularFactor: number[];
+        glossinessFactor: number;
+        specularGlossinessTexture: IGLTFTextureInfo;
+    }
+
+    export class KHRMaterialsPbrSpecularGlossiness extends GLTFLoaderExtension {
+        public get name(): string {
+            return "KHR_materials_pbrSpecularGlossiness";
+        }
+
+        protected loadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean {
+            if (!material.extensions) {
+                return false;
+            }
+
+            var properties = material.extensions[this.name] as IKHRMaterialsPbrSpecularGlossiness;
+            if (!properties) {
+                return false;
+            }
+
+            loader.createPbrMaterial(material);
+            loader.loadMaterialBaseProperties(material);
+            this._loadSpecularGlossinessProperties(loader, material, properties);
+            assign(material.babylonMaterial);
+            return true;
+        }
+
+        private _loadSpecularGlossinessProperties(loader: GLTFLoader, material: IGLTFMaterial, properties: IKHRMaterialsPbrSpecularGlossiness): void {
+            var babylonMaterial = material.babylonMaterial as PBRMaterial;
+
+            babylonMaterial.albedoColor = properties.diffuseFactor ? Color3.FromArray(properties.diffuseFactor) : new Color3(1, 1, 1);
+            babylonMaterial.reflectivityColor = properties.specularFactor ? Color3.FromArray(properties.specularFactor) : new Color3(1, 1, 1);
+            babylonMaterial.microSurface = properties.glossinessFactor === undefined ? 1 : properties.glossinessFactor;
+
+            if (properties.diffuseTexture) {
+                babylonMaterial.albedoTexture = loader.loadTexture(properties.diffuseTexture);
+                loader.loadMaterialAlphaProperties(material);
+            }
+
+            if (properties.specularGlossinessTexture) {
+                babylonMaterial.reflectivityTexture = loader.loadTexture(properties.specularGlossinessTexture);
+                babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
+            }
+        }
+    }
+
+    GLTFLoader.RegisterExtension(new KHRMaterialsPbrSpecularGlossiness());
+}

+ 57 - 0
loaders/src/glTF/2.0/Extensions/MSFT_lod.ts

@@ -0,0 +1,57 @@
+/// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GLTF2.Extensions {
+    interface IMSFTLOD {
+        ids: number[];
+    }
+
+    export class MSFTLOD extends GLTFLoaderExtension {
+        public get name() {
+            return "MSFT_lod";
+        }
+
+        protected loadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean {
+            if (!material.extensions) {
+                return false;
+            }
+
+            var properties = material.extensions[this.name] as IMSFTLOD;
+            if (!properties) {
+                return false;
+            }
+
+            // Clear out the extension so that it won't get loaded again.
+            material.extensions[this.name] = undefined;
+
+            // Tell the loader not to clear its state until the highest LOD is loaded.
+            loader.addLoaderPendingData(material);
+
+            // Start with the lowest quality LOD.
+            var materialLODs = [material.index, ...properties.ids];
+            this.loadMaterialLOD(loader, material, materialLODs, materialLODs.length - 1, assign);
+
+            return true;
+        }
+
+        private loadMaterialLOD(loader: GLTFLoader, material: IGLTFMaterial, materialLODs: number[], lod: number, assign: (material: Material) => void): void {
+            loader.loadMaterial(materialLODs[lod], babylonMaterial => {
+                babylonMaterial.name += ".LOD" + lod;
+                assign(babylonMaterial);
+
+                // Loading is complete if this is the highest quality LOD.
+                if (lod === 0) {
+                    loader.removeLoaderPendingData(material);
+                    return;
+                }
+
+                // Load the next LOD when all of the textures are loaded.
+                BaseTexture.WhenAllReady(babylonMaterial.getActiveTextures(), () => {
+                    this.loadMaterialLOD(loader, material, materialLODs, lod - 1, assign);
+                });
+            });
+
+        }
+    }
+
+    GLTFLoader.RegisterExtension(new MSFTLOD());
+}

+ 226 - 160
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -2,13 +2,22 @@
 
 module BABYLON.GLTF2 {
     export class GLTFLoader implements IGLTFLoader {
+        private _parent: GLTFFileLoader;
         private _gltf: IGLTF;
-        private _pendingCount: number;
-        private _onLoaded: () => void;
         private _errors: string[];
         private _babylonScene: Scene;
         private _rootUrl: string;
         private _defaultMaterial: PBRMaterial;
+        private _onSuccess: () => void;
+        private _onError: () => void;
+
+        private _renderReady: boolean;
+
+        // Count of pending work that needs to complete before the asset is rendered.
+        private _renderPendingCount: number;
+
+        // Count of pending work that needs to complete before the loader is cleared.
+        private _loaderPendingCount: number;
 
         public static Extensions: { [name: string]: GLTFLoaderExtension } = {};
 
@@ -18,27 +27,22 @@ module BABYLON.GLTF2 {
                 return;
             }
 
-            this.Extensions[extension.name] = extension;
-        }
-
-        public static LoadMaterial(index: number): IGLTFMaterial {
-            return (<GLTFLoader>BABYLON.GLTFFileLoader.GLTFLoaderV2)._loadMaterial(index);
-        }
+            GLTFLoader.Extensions[extension.name] = extension;
 
-        public static LoadCoreMaterial(index: number): Material {
-            return (<GLTFLoader>BABYLON.GLTFFileLoader.GLTFLoaderV2)._loadCoreMaterial(index);
+            // Keep the order of registration so that extensions registered first are called first.
+            GLTFLoaderExtension._Extensions.push(extension);
         }
 
-        public static LoadCommonMaterialProperties(material: IGLTFMaterial): void {
-            return (<GLTFLoader>BABYLON.GLTFFileLoader.GLTFLoaderV2)._loadCommonMaterialProperties(material);
+        public get gltf(): IGLTF {
+            return this._gltf;
         }
 
-        public static LoadAlphaProperties(material: IGLTFMaterial): void {
-            return (<GLTFLoader>BABYLON.GLTFFileLoader.GLTFLoaderV2)._loadAlphaProperties(material);
+        public get babylonScene(): Scene {
+            return this._babylonScene;
         }
 
-        public static LoadTexture(textureInfo: IGLTFTextureInfo): Texture {
-            return (<GLTFLoader>BABYLON.GLTFFileLoader.GLTFLoaderV2)._loadTexture(textureInfo);
+        public constructor(parent: GLTFFileLoader) {
+            this._parent = parent;
         }
 
         public importMeshAsync(meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void): void {
@@ -80,25 +84,35 @@ module BABYLON.GLTF2 {
             this._babylonScene = scene;
             this._rootUrl = rootUrl;
 
-            this._onLoaded = () => {
-                this._showMeshes();
-                this._startAnimations();
-
-                if (this._errors.length === 0) {
-                    onSuccess();
-                }
-                else {
-                    this._errors.forEach(error => Tools.Error(error));
-                    onError();
-                }
-
-                this._clear();
-            };
+            this._onSuccess = onSuccess;
+            this._onError = onError;
 
-            this._addPendingData(this);
+            this.addPendingData(this);
             this._loadScene(nodeNames);
             this._loadAnimations();
-            this._removePendingData(this);
+            this.removePendingData(this);
+        }
+
+        private _onRenderReady(): void {
+            this._showMeshes();
+            this._startAnimations();
+
+            if (this._errors.length === 0) {
+                this._onSuccess();
+            }
+            else {
+                this._errors.forEach(error => Tools.Error(error));
+                this._errors = [];
+                this._onError();
+            }
+        }
+
+        private _onLoaderComplete(): void {
+            this._errors.forEach(error => Tools.Error(error));
+            this._errors = [];
+            this._clear();
+
+            this._parent.onComplete();
         }
 
         private _loadData(data: IGLTFLoaderData): void {
@@ -149,14 +163,6 @@ module BABYLON.GLTF2 {
         }
 
         private _clear(): void {
-            this._gltf = undefined;
-            this._pendingCount = 0;
-            this._onLoaded = undefined;
-            this._errors = [];
-            this._babylonScene = undefined;
-            this._rootUrl = undefined;
-            this._defaultMaterial = undefined;
-
             // Revoke object urls created during load
             if (this._gltf && this._gltf.textures) {
                 for (var i = 0; i < this._gltf.textures.length; i++) {
@@ -166,16 +172,49 @@ module BABYLON.GLTF2 {
                     }
                 }
             }
+
+            this._gltf = undefined;
+            this._errors = [];
+            this._babylonScene = undefined;
+            this._rootUrl = undefined;
+            this._defaultMaterial = undefined;
+            this._onSuccess = undefined;
+            this._onError = undefined;
+            this._renderReady = false;
+            this._renderPendingCount = 0;
+            this._loaderPendingCount = 0;
         }
 
         private _loadScene(nodeNames: any): void {
-            nodeNames = (nodeNames === "") ? null : nodeNames;
-            nodeNames = (nodeNames instanceof Array) ? nodeNames : [nodeNames];
-
             var scene = this._gltf.scenes[this._gltf.scene || 0];
+            var nodeIndices = scene.nodes;
+
+            this._traverseNodes(nodeIndices, (node, index, parentNode) => {
+                node.index = index;
+                node.parent = parentNode;
+                return true;
+            });
+
+            if (nodeNames) {
+                if (!(nodeNames instanceof Array)) {
+                    nodeNames = [nodeNames];
+                }
+
+                var filteredNodeIndices = new Array<number>();
+                this._traverseNodes(nodeIndices, node => {
+                    if (nodeNames.indexOf(node.name) === -1) {
+                        return true;
+                    }
+
+                    filteredNodeIndices.push(node.index);
+                    return false;
+                });
+
+                nodeIndices = filteredNodeIndices;
+            }
 
-            this._traverseScene(nodeNames, scene, node => this._loadSkin(node));
-            this._traverseScene(nodeNames, scene, (node, parentNode) => this._loadMesh(node, parentNode));
+            this._traverseNodes(nodeIndices, node => this._loadSkin(node));
+            this._traverseNodes(nodeIndices, node => this._loadMesh(node));
         }
 
         private _loadSkin(node: IGLTFNode): boolean {
@@ -201,7 +240,7 @@ module BABYLON.GLTF2 {
 
                 var accessor = this._gltf.accessors[skin.inverseBindMatrices];
                 this._loadAccessorAsync(accessor, data => {
-                    this._traverseNode(null, skin.skeleton, (node, parent) => this._updateBone(node, parent, skin, <Float32Array>data));
+                    this._traverseNode(skin.skeleton, (node, index, parent) => this._updateBone(node, parent, skin, <Float32Array>data));
                 });
             }
 
@@ -240,7 +279,7 @@ module BABYLON.GLTF2 {
             return babylonBone;
         }
 
-        private _loadMesh(node: IGLTFNode, parentNode: IGLTFNode): boolean {
+        private _loadMesh(node: IGLTFNode): boolean {
             var babylonMesh = new Mesh(node.name || "mesh" + node.index, this._babylonScene);
             babylonMesh.isVisible = false;
 
@@ -251,7 +290,7 @@ module BABYLON.GLTF2 {
                 this._loadMeshData(node, mesh, babylonMesh);
             }
 
-            babylonMesh.parent = parentNode ? parentNode.babylonMesh : null;
+            babylonMesh.parent = node.parent ? node.parent.babylonMesh : null;
             node.babylonMesh = babylonMesh;
 
             node.babylonAnimationTargets = node.babylonAnimationTargets || [];
@@ -271,10 +310,9 @@ module BABYLON.GLTF2 {
 
         private _loadMeshData(node: IGLTFNode, mesh: IGLTFMesh, babylonMesh: Mesh): void {
             babylonMesh.name = mesh.name || babylonMesh.name;
-            babylonMesh.subMeshes = [];
 
-            var multiMaterial = new MultiMaterial(babylonMesh.name, this._babylonScene);
-            babylonMesh.material = multiMaterial;
+            var babylonMultiMaterial = new MultiMaterial(babylonMesh.name, this._babylonScene);
+            babylonMesh.material = babylonMultiMaterial;
 
             var geometry = new Geometry(babylonMesh.name, this._babylonScene, null, false, babylonMesh);
             var vertexData = new VertexData();
@@ -283,9 +321,9 @@ module BABYLON.GLTF2 {
 
             var subMeshInfos: { materialIndex: number, verticesStart: number, verticesCount: number, indicesStart: number, indicesCount: number }[] = [];
 
-            var primitivesLoaded = 0;
-            var numPrimitives = mesh.primitives.length;
-            for (var i = 0; i < numPrimitives; i++) {
+            var loadedPrimitives = 0;
+            var totalPrimitives = mesh.primitives.length;
+            for (let i = 0; i < totalPrimitives; i++) {
                 let primitive = mesh.primitives[i];
                 if (primitive.mode && primitive.mode !== EMeshPrimitiveMode.TRIANGLES) {
                     // TODO: handle other primitive modes
@@ -298,25 +336,40 @@ module BABYLON.GLTF2 {
                     this._loadMorphTargetsData(mesh, primitive, subVertexData, babylonMesh);
 
                     subMeshInfos.push({
-                        materialIndex: multiMaterial.subMaterials.length,
+                        materialIndex: i,
                         verticesStart: vertexData.positions.length,
                         verticesCount: subVertexData.positions.length,
                         indicesStart: vertexData.indices.length,
                         indicesCount: subVertexData.indices.length
                     });
 
-                    var subMaterial = primitive.material === undefined ? this._getDefaultMaterial() : GLTFLoaderExtension.LoadMaterial(primitive.material);
-                    multiMaterial.subMaterials.push(subMaterial);
                     vertexData.merge(subVertexData);
 
-                    if (++primitivesLoaded === numPrimitives) {
+                    if (primitive.material === undefined) {
+                        babylonMultiMaterial.subMaterials[i] = this._getDefaultMaterial();
+                    }
+                    else {
+                        this.loadMaterial(primitive.material, (babylonSubMaterial: Material) => {
+                            if (this._renderReady) {
+                                babylonSubMaterial.forceCompilation(babylonMesh, babylonSubMaterial => {
+                                    babylonMultiMaterial.subMaterials[i] = babylonSubMaterial;
+                                    this._parent.onMaterialLoaded(babylonSubMaterial);
+                                });
+                            }
+                            else {
+                                babylonMultiMaterial.subMaterials[i] = babylonSubMaterial;
+                                this._parent.onMaterialLoaded(babylonSubMaterial);
+                            }
+                        });
+                    }
+
+                    if (++loadedPrimitives === totalPrimitives) {
                         geometry.setAllVerticesData(vertexData, false);
 
-                        // Sub meshes must be created after setting vertex data because of mesh._createGlobalSubMesh.
-                        for (var i = 0; i < subMeshInfos.length; i++) {
-                            var info = subMeshInfos[i];
-                            new SubMesh(info.materialIndex, info.verticesStart, info.verticesCount, info.indicesStart, info.indicesCount, babylonMesh);
-                        }
+                        // TODO: optimize this so that sub meshes can be created without being overwritten after setting vertex data.
+                        // Sub meshes must be cleared and created after setting vertex data because of mesh._createGlobalSubMesh.
+                        babylonMesh.subMeshes = [];
+                        subMeshInfos.forEach(info => new SubMesh(info.materialIndex, info.verticesStart, info.verticesCount, info.indicesStart, info.indicesCount, babylonMesh));
                     }
                 });
             }
@@ -332,7 +385,7 @@ module BABYLON.GLTF2 {
             var vertexData = new VertexData();
 
             var loadedAttributes = 0;
-            var numAttributes = Object.keys(attributes).length;
+            var totalAttributes = Object.keys(attributes).length;
             for (let semantic in attributes) {
                 var accessor = this._gltf.accessors[attributes[semantic]];
                 this._loadAccessorAsync(accessor, data => {
@@ -366,7 +419,7 @@ module BABYLON.GLTF2 {
                             break;
                     }
 
-                    if (++loadedAttributes === numAttributes) {
+                    if (++loadedAttributes === totalAttributes) {
                         var indicesAccessor = this._gltf.accessors[primitive.indices];
                         if (indicesAccessor) {
                             this._loadAccessorAsync(indicesAccessor, data => {
@@ -469,39 +522,22 @@ module BABYLON.GLTF2 {
             babylonMesh.scaling = scaling;
         }
 
-        private _traverseScene(nodeNames: string[], scene: IGLTFScene, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean): void {
-            var nodes = scene.nodes;
-
-            if (nodes) {
-                for (var i = 0; i < nodes.length; i++) {
-                    this._traverseNode(nodeNames, nodes[i], action);
-                }
+        private _traverseNodes(indices: number[], action: (node: IGLTFNode, index: number, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode = null): void {
+            for (var i = 0; i < indices.length; i++) {
+                this._traverseNode(indices[i], action, parentNode);
             }
         }
 
-        private _traverseNode(nodeNames: string[], index: number, action: (node: IGLTFNode, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode = null): void {
+        private _traverseNode(index: number, action: (node: IGLTFNode, index: number, parentNode: IGLTFNode) => boolean, parentNode: IGLTFNode = null): void {
             var node = this._gltf.nodes[index];
 
-            if (nodeNames) {
-                if (nodeNames.indexOf(node.name)) {
-                    // load all children
-                    nodeNames = null;
-                }
-                else {
-                    // skip this node tree
-                    return;
-                }
-            }
-
-            node.index = index;
-
-            if (!action(node, parentNode)) {
+            if (!action(node, index, parentNode)) {
                 return;
             }
 
             if (node.children) {
                 for (var i = 0; i < node.children.length; i++) {
-                    this._traverseNode(nodeNames, node.children[i], action, node);
+                    this._traverseNode(node.children[i], action, node);
                 }
             }
         }
@@ -650,12 +686,12 @@ module BABYLON.GLTF2 {
 
         private _loadBufferAsync(index: number, onSuccess: (data: ArrayBufferView) => void): void {
             var buffer = this._gltf.buffers[index];
-            this._addPendingData(buffer);
+            this.addPendingData(buffer);
 
             if (buffer.loadedData) {
                 setTimeout(() => {
                     onSuccess(buffer.loadedData);
-                    this._removePendingData(buffer);
+                    this.removePendingData(buffer);
                 });
             }
             else if (GLTFUtils.IsBase64(buffer.uri)) {
@@ -663,20 +699,20 @@ module BABYLON.GLTF2 {
                 buffer.loadedData = new Uint8Array(data);
                 setTimeout(() => {
                     onSuccess(buffer.loadedData);
-                    this._removePendingData(buffer);
+                    this.removePendingData(buffer);
                 });
             }
             else if (buffer.loadedObservable) {
                 buffer.loadedObservable.add(buffer => {
                     onSuccess(buffer.loadedData);
-                    this._removePendingData(buffer);
+                    this.removePendingData(buffer);
                 });
             }
             else {
                 buffer.loadedObservable = new Observable<IGLTFBuffer>();
                 buffer.loadedObservable.add(buffer => {
                     onSuccess(buffer.loadedData);
-                    this._removePendingData(buffer);
+                    this.removePendingData(buffer);
                 });
 
                 Tools.LoadFile(this._rootUrl + buffer.uri, data => {
@@ -685,7 +721,7 @@ module BABYLON.GLTF2 {
                     buffer.loadedObservable = null;
                 }, null, null, true, request => {
                     this._errors.push("Failed to load file '" + buffer.uri + "': " + request.statusText + "(" + request.status + ")");
-                    this._removePendingData(buffer);
+                    this.removePendingData(buffer);
                 });
             }
         }
@@ -738,13 +774,32 @@ module BABYLON.GLTF2 {
             this._loadBufferViewAsync(bufferView, byteOffset, byteLength, accessor.componentType, onSuccess);
         }
 
-        private _addPendingData(data: any) {
-            this._pendingCount++;
+        public addPendingData(data: any) {
+            if (!this._renderReady) {
+                this._renderPendingCount++;
+            }
+
+            this.addLoaderPendingData(data);
+        }
+
+        public removePendingData(data: any) {
+            if (!this._renderReady) {
+                if (--this._renderPendingCount === 0) {
+                    this._renderReady = true;
+                    this._onRenderReady();
+                }
+            }
+
+            this.removeLoaderPendingData(data);
+        }
+
+        public addLoaderPendingData(data: any) {
+            this._loaderPendingCount++;
         }
 
-        private _removePendingData(data: any) {
-            if (--this._pendingCount === 0) {
-                this._onLoaded();
+        public removeLoaderPendingData(data: any) {
+            if (--this._loaderPendingCount === 0) {
+                this._onLoaderComplete();
             }
         }
 
@@ -765,104 +820,114 @@ module BABYLON.GLTF2 {
             return this._defaultMaterial;
         }
 
-        private _loadMaterial(index: number): IGLTFMaterial {
-            var materials = this._gltf.materials;
-            var material = materials ? materials[index] : null;
-            if (!material) {
-                Tools.Warn("Material index (" + index + ") does not exist");
-                return null;
+        private _loadMaterialMetallicRoughnessProperties(material: IGLTFMaterial): void {
+            var babylonMaterial = material.babylonMaterial as PBRMaterial;
+
+            // Ensure metallic workflow
+            babylonMaterial.metallic = 1;
+            babylonMaterial.roughness = 1;
+
+            var properties = material.pbrMetallicRoughness;
+            if (!properties) {
+                return;
             }
 
-            material.babylonMaterial = new PBRMaterial(material.name || "mat" + index, this._babylonScene);
-            material.babylonMaterial.sideOrientation = Material.CounterClockWiseSideOrientation;
-            material.babylonMaterial.useScalarInLinearSpace = true;
-            return material;
-        }
+            babylonMaterial.albedoColor = properties.baseColorFactor ? Color3.FromArray(properties.baseColorFactor) : new Color3(1, 1, 1);
+            babylonMaterial.metallic = properties.metallicFactor === undefined ? 1 : properties.metallicFactor;
+            babylonMaterial.roughness = properties.roughnessFactor === undefined ? 1 : properties.roughnessFactor;
 
-        private _loadCoreMaterial(index: number): Material {
-            var material = this._loadMaterial(index);
-            if (!material) {
-                return null;
+            if (properties.baseColorTexture) {
+                babylonMaterial.albedoTexture = this.loadTexture(properties.baseColorTexture);
+                this.loadMaterialAlphaProperties(material);
             }
 
-            this._loadCommonMaterialProperties(material);
+            if (properties.metallicRoughnessTexture) {
+                babylonMaterial.metallicTexture = this.loadTexture(properties.metallicRoughnessTexture);
+                babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
+                babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
+                babylonMaterial.useRoughnessFromMetallicTextureAlpha = false;
+            }
+        }
 
-            // Ensure metallic workflow
-            material.babylonMaterial.metallic = 1;
-            material.babylonMaterial.roughness = 1;
+        public loadMaterial(index: number, assign: (material: Material) => void): void {
+            var material = this._gltf.materials[index];
+            material.index = index;
 
-            var properties = material.pbrMetallicRoughness;
-            if (properties) {
-                material.babylonMaterial.albedoColor = properties.baseColorFactor ? Color3.FromArray(properties.baseColorFactor) : new Color3(1, 1, 1);
-                material.babylonMaterial.metallic = properties.metallicFactor === undefined ? 1 : properties.metallicFactor;
-                material.babylonMaterial.roughness = properties.roughnessFactor === undefined ? 1 : properties.roughnessFactor;
-
-                if (properties.baseColorTexture) {
-                    material.babylonMaterial.albedoTexture = this._loadTexture(properties.baseColorTexture);
-                    this._loadAlphaProperties(material);
-                }
+            if (material.babylonMaterial) {
+                assign(material.babylonMaterial);
+                return;
+            }
 
-                if (properties.metallicRoughnessTexture) {
-                    material.babylonMaterial.metallicTexture = this._loadTexture(properties.metallicRoughnessTexture);
-                    material.babylonMaterial.useMetallnessFromMetallicTextureBlue = true;
-                    material.babylonMaterial.useRoughnessFromMetallicTextureGreen = true;
-                    material.babylonMaterial.useRoughnessFromMetallicTextureAlpha = false;
-                }
+            if (GLTFLoaderExtension.LoadMaterial(this, material, assign)) {
+                return;
             }
 
-            return material.babylonMaterial;
+            this.createPbrMaterial(material);
+            this.loadMaterialBaseProperties(material);
+            this._loadMaterialMetallicRoughnessProperties(material);
+            assign(material.babylonMaterial);
         }
 
-        private _loadCommonMaterialProperties(material: IGLTFMaterial): void {
-            material.babylonMaterial.useEmissiveAsIllumination = (material.emissiveFactor || material.emissiveTexture) ? true : false;
-            material.babylonMaterial.emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0);
+        public createPbrMaterial(material: IGLTFMaterial): void {
+            var babylonMaterial = new PBRMaterial(material.name || "mat" + material.index, this._babylonScene);
+            babylonMaterial.sideOrientation = Material.CounterClockWiseSideOrientation;
+            babylonMaterial.useScalarInLinearSpace = true;
+            material.babylonMaterial = babylonMaterial;
+        }
+
+        public loadMaterialBaseProperties(material: IGLTFMaterial): void {
+            var babylonMaterial = material.babylonMaterial as PBRMaterial;
+
+            babylonMaterial.useEmissiveAsIllumination = (material.emissiveFactor || material.emissiveTexture) ? true : false;
+            babylonMaterial.emissiveColor = material.emissiveFactor ? Color3.FromArray(material.emissiveFactor) : new Color3(0, 0, 0);
             if (material.doubleSided) {
-                material.babylonMaterial.backFaceCulling = false;
-                material.babylonMaterial.twoSidedLighting = true;
+                babylonMaterial.backFaceCulling = false;
+                babylonMaterial.twoSidedLighting = true;
             }
 
             if (material.normalTexture) {
-                material.babylonMaterial.bumpTexture = this._loadTexture(material.normalTexture);
+                babylonMaterial.bumpTexture = this.loadTexture(material.normalTexture);
                 if (material.normalTexture.scale !== undefined) {
-                    material.babylonMaterial.bumpTexture.level = material.normalTexture.scale;
+                    babylonMaterial.bumpTexture.level = material.normalTexture.scale;
                 }
             }
 
             if (material.occlusionTexture) {
-                material.babylonMaterial.ambientTexture = this._loadTexture(material.occlusionTexture);
-                material.babylonMaterial.useAmbientInGrayScale = true;
+                babylonMaterial.ambientTexture = this.loadTexture(material.occlusionTexture);
+                babylonMaterial.useAmbientInGrayScale = true;
                 if (material.occlusionTexture.strength !== undefined) {
-                    material.babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
+                    babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength;
                 }
             }
 
             if (material.emissiveTexture) {
-                material.babylonMaterial.emissiveTexture = this._loadTexture(material.emissiveTexture);
+                babylonMaterial.emissiveTexture = this.loadTexture(material.emissiveTexture);
             }
         }
 
-        private _loadAlphaProperties(material: IGLTFMaterial): void {
+        public loadMaterialAlphaProperties(material: IGLTFMaterial): void {
+            var babylonMaterial = material.babylonMaterial as PBRMaterial;
+
             var alphaMode = material.alphaMode || "OPAQUE";
             switch (alphaMode) {
                 case "OPAQUE":
                     // default is opaque
                     break;
                 case "MASK":
-                    material.babylonMaterial.albedoTexture.hasAlpha = true;
-                    material.babylonMaterial.useAlphaFromAlbedoTexture = false;
-                    material.babylonMaterial.alphaMode = Engine.ALPHA_DISABLE;
+                    babylonMaterial.albedoTexture.hasAlpha = true;
+                    babylonMaterial.useAlphaFromAlbedoTexture = false;
                     break;
                 case "BLEND":
-                    material.babylonMaterial.albedoTexture.hasAlpha = true;
-                    material.babylonMaterial.useAlphaFromAlbedoTexture = true;
-                    material.babylonMaterial.alphaMode = Engine.ALPHA_COMBINE;
+                    babylonMaterial.albedoTexture.hasAlpha = true;
+                    babylonMaterial.useAlphaFromAlbedoTexture = true;
                     break;
                 default:
-                    Tools.Error("Invalid alpha mode '" + material.alphaMode + "'");
+                    Tools.Warn("Invalid alpha mode '" + material.alphaMode + "'");
+                    break;
             }
         }
 
-        private _loadTexture(textureInfo: IGLTFTextureInfo): Texture {
+        public loadTexture(textureInfo: IGLTFTextureInfo): Texture {
             var texture = this._gltf.textures[textureInfo.index];
             var texCoord = textureInfo.texCoord || 0;
 
@@ -911,26 +976,27 @@ module BABYLON.GLTF2 {
             var noMipMaps = (sampler.minFilter === ETextureMinFilter.NEAREST || sampler.minFilter === ETextureMinFilter.LINEAR);
             var samplingMode = GLTFUtils.GetTextureFilterMode(sampler.minFilter);
 
-            this._addPendingData(texture);
+            this.addPendingData(texture);
             var babylonTexture = new Texture(url, this._babylonScene, noMipMaps, false, samplingMode, () => {
-                this._removePendingData(texture);
+                this.removePendingData(texture);
             }, () => {
                 this._errors.push("Failed to load texture '" + source.uri + "'");
-                this._removePendingData(texture);
+                this.removePendingData(texture);
             });
 
             babylonTexture.coordinatesIndex = texCoord;
             babylonTexture.wrapU = GLTFUtils.GetWrapMode(sampler.wrapS);
             babylonTexture.wrapV = GLTFUtils.GetWrapMode(sampler.wrapT);
-            babylonTexture.name = texture.name;
+            babylonTexture.name = texture.name || "texture" + textureInfo.index;
 
             // Cache the texture
             texture.babylonTextures = texture.babylonTextures || [];
             texture.babylonTextures[texCoord] = babylonTexture;
 
+            this._parent.onTextureLoaded(babylonTexture);
             return babylonTexture;
         }
     }
 
-    BABYLON.GLTFFileLoader.GLTFLoaderV2 = new GLTFLoader();
+    BABYLON.GLTFFileLoader.CreateGLTFLoaderV2 = parent => new GLTFLoader(parent);
 }

+ 21 - 21
loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts

@@ -2,36 +2,36 @@
 
 module BABYLON.GLTF2 {
     export abstract class GLTFLoaderExtension {
-        private _name: string;
-
         public enabled: boolean = true;
 
-        public constructor(name: string) {
-            this._name = name;
-        }
+        public abstract get name(): string;
+
+        protected loadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean { return false; }
+
+        //
+        // Utilities
+        //
+
+        public static _Extensions: GLTFLoaderExtension[] = [];
 
-        public get name(): string {
-            return this._name;
+        public static LoadMaterial(loader: GLTFLoader, material: IGLTFMaterial, assign: (material: Material) => void): boolean {
+            return this._ApplyExtensions(extension => extension.loadMaterial(loader, material, assign));
         }
 
-        protected loadMaterial(index: number): Material { return null; }
+        private static _ApplyExtensions(action: (extension: GLTFLoaderExtension) => boolean) {
+            var extensions = GLTFLoaderExtension._Extensions;
+            if (!extensions) {
+                return;
+            }
 
-        // ---------
-        // Utilities
-        // ---------
-
-        public static LoadMaterial(index: number): Material {
-            for (var extensionName in GLTFLoader.Extensions) {
-                var extension = GLTFLoader.Extensions[extensionName];
-                if (extension.enabled) {
-                    var babylonMaterial = extension.loadMaterial(index);
-                    if (babylonMaterial) {
-                        return babylonMaterial;
-                    }
+            for (var i = 0; i < extensions.length; i++) {
+                var extension = extensions[i];
+                if (extension.enabled && action(extension)) {
+                    return true;
                 }
             }
 
-            return GLTFLoader.LoadCoreMaterial(index);
+            return false;
         }
     }
 }

+ 4 - 7
loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts

@@ -108,16 +108,11 @@ module BABYLON.GLTF2 {
         targets?: any[];
     }
 
-    export interface IGLTFAssetProfile extends IGLTFProperty {
-        api?: string;
-        version?: string;
-    }
-
     export interface IGLTFAsset extends IGLTFChildRootProperty {
         copyright?: string;
         generator?: string;
-        profile?: IGLTFAssetProfile;
         version: string;
+        minVersion?: string;
     }
 
     export interface IGLTFBuffer extends IGLTFChildRootProperty {
@@ -189,7 +184,8 @@ module BABYLON.GLTF2 {
         doubleSided?: boolean;
 
         // Runtime values
-        babylonMaterial?: PBRMaterial;
+        index?: number;
+        babylonMaterial?: Material;
     }
 
     export interface IGLTFMeshPrimitive extends IGLTFProperty {
@@ -218,6 +214,7 @@ module BABYLON.GLTF2 {
 
         // Runtime values
         index?: number;
+        parent?: IGLTFNode;
         babylonMesh?: Mesh;
         babylonSkinToBones?: { [skin: number]: Bone };
         babylonAnimationTargets?: Node[];

+ 0 - 53
loaders/src/glTF/2.0/babylon.glTFMaterialsPbrSpecularGlossinessExtension.ts

@@ -1,53 +0,0 @@
-/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON.GLTF2 {
-    interface IGLTFMaterialsPbrSpecularGlossiness {
-        diffuseFactor: number[];
-        diffuseTexture: IGLTFTextureInfo;
-        specularFactor: number[];
-        glossinessFactor: number;
-        specularGlossinessTexture: IGLTFTextureInfo;
-    }
-
-    export class GLTFMaterialsPbrSpecularGlossinessExtension extends GLTFLoaderExtension {
-        constructor() {
-            super("KHR_materials_pbrSpecularGlossiness");
-        }
-
-        protected loadMaterial(index: number): Material {
-            var material = GLTFLoader.LoadMaterial(index);
-            if (!material || !material.extensions) return null;
-
-            var properties: IGLTFMaterialsPbrSpecularGlossiness = material.extensions[this.name];
-            if (!properties) return null;
-
-            GLTFLoader.LoadCommonMaterialProperties(material);
-
-            //
-            // Load Factors
-            //
-
-            material.babylonMaterial.albedoColor = properties.diffuseFactor ? Color3.FromArray(properties.diffuseFactor) : new Color3(1, 1, 1);
-            material.babylonMaterial.reflectivityColor = properties.specularFactor ? Color3.FromArray(properties.specularFactor) : new Color3(1, 1, 1);
-            material.babylonMaterial.microSurface = properties.glossinessFactor === undefined ? 1 : properties.glossinessFactor;
-
-            //
-            // Load Textures
-            //
-
-            if (properties.diffuseTexture) {
-                material.babylonMaterial.albedoTexture = GLTFLoader.LoadTexture(properties.diffuseTexture);
-                GLTFLoader.LoadAlphaProperties(material);
-            }
-
-            if (properties.specularGlossinessTexture) {
-                material.babylonMaterial.reflectivityTexture = GLTFLoader.LoadTexture(properties.specularGlossinessTexture);
-                material.babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
-            }
-
-            return material.babylonMaterial;
-        }
-    }
-
-    GLTFLoader.RegisterExtension(new GLTFMaterialsPbrSpecularGlossinessExtension());
-}

+ 18 - 15
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -7,17 +7,23 @@ module BABYLON {
     }
 
     export interface IGLTFLoader {
-        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror: () => void) => void;
-        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: () => void, onerror: () => void) => void;
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError: () => void) => void;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: () => void, onError: () => void) => void;
     }
 
     export class GLTFFileLoader implements ISceneLoaderPluginAsync {
-        public static GLTFLoaderV1: IGLTFLoader = null;
-        public static GLTFLoaderV2: IGLTFLoader = null;
+        public static CreateGLTFLoaderV1: (parent: GLTFFileLoader) => IGLTFLoader;
+        public static CreateGLTFLoaderV2: (parent: GLTFFileLoader) => IGLTFLoader;
 
+        // V1 options
         public static HomogeneousCoordinates: boolean = false;
         public static IncrementalLoading: boolean = true;
 
+        // V2 options
+        public onTextureLoaded: (texture: BaseTexture) => void;
+        public onMaterialLoaded: (material: Material) => void;
+        public onComplete: () => void;
+
         public extensions: ISceneLoaderPluginExtensions = {
             ".gltf": { isBinary: false },
             ".glb": { isBinary: true }
@@ -79,19 +85,14 @@ module BABYLON {
                 }
             }
 
-            var loaders = {
-                1: GLTFFileLoader.GLTFLoaderV1,
-                2: GLTFFileLoader.GLTFLoaderV2
+            var createLoader = {
+                1: GLTFFileLoader.CreateGLTFLoaderV1,
+                2: GLTFFileLoader.CreateGLTFLoaderV2
             };
 
-            var loader = loaders[version.major];
-            if (loader === undefined) {
-                Tools.Error("Unsupported version");
-                return null;
-            }
-
+            var loader = createLoader[version.major](this);
             if (loader === null) {
-                Tools.Error("v" + version.major + " loader is not available");
+                Tools.Error("Unsupported version");
                 return null;
             }
 
@@ -279,5 +280,7 @@ module BABYLON {
         }
     }
 
-    BABYLON.SceneLoader.RegisterPlugin(new GLTFFileLoader());
+    if (BABYLON.SceneLoader) {
+        BABYLON.SceneLoader.RegisterPlugin(new GLTFFileLoader());
+    }
 }

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

@@ -270,6 +270,16 @@ module BABYLON {
             return results;
         }
 
+        public getActiveTextures(): BaseTexture[] {
+            var activeTextures = super.getActiveTextures();
+
+            if (this._diffuseTexture) {
+                activeTextures.push(this._diffuseTexture);
+            }
+
+            return activeTextures;
+        }
+
         public dispose(forceDisposeEffect?: boolean): void {
             if (this._diffuseTexture) {
                 this._diffuseTexture.dispose();

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

@@ -258,6 +258,24 @@ module BABYLON {
             return results;
         }
 
+        public getActiveTextures(): BaseTexture[] {
+            var activeTextures = super.getActiveTextures();
+
+            if (this._diffuseTexture) {
+                activeTextures.push(this._diffuseTexture);
+            }
+
+            if (this._distortionTexture) {
+                activeTextures.push(this._distortionTexture);
+            }
+
+            if (this._opacityTexture) {
+                activeTextures.push(this._opacityTexture);
+            }
+
+            return activeTextures;
+        }
+
         public dispose(forceDisposeEffect?: boolean): void {
             if (this._diffuseTexture) {
                 this._diffuseTexture.dispose();

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

@@ -369,6 +369,20 @@ module BABYLON {
             return results;
         }
 
+        public getActiveTextures(): BaseTexture[] {
+            var activeTextures = super.getActiveTextures();
+
+            if (this._diffuseTexture) {
+                activeTextures.push(this._diffuseTexture);
+            }
+
+            if (this._heightTexture) {
+                activeTextures.push(this._heightTexture);
+            }
+
+            return activeTextures;
+        }
+
         public dispose(forceDisposeEffect?: boolean): void {
             if (this.diffuseTexture) {
                 this.diffuseTexture.dispose();

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

@@ -339,6 +339,16 @@ module BABYLON {
             return results;
         }
 
+        public getActiveTextures(): BaseTexture[] {
+            var activeTextures = super.getActiveTextures();
+
+            if (this._diffuseTexture) {
+                activeTextures.push(this._diffuseTexture);
+            }
+
+            return activeTextures;
+        }
+
         public dispose(forceDisposeEffect?: boolean): void {
             if (this.diffuseTexture) {
                 this.diffuseTexture.dispose();

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

@@ -293,6 +293,16 @@ module BABYLON {
             return results;
         }
 
+        public getActiveTextures(): BaseTexture[] {
+            var activeTextures = super.getActiveTextures();
+
+            if (this._diffuseTexture) {
+                activeTextures.push(this._diffuseTexture);
+            }
+
+            return activeTextures;
+        }
+
         public dispose(forceDisposeEffect?: boolean): void {
             if (this.diffuseTexture) {
                 this.diffuseTexture.dispose();

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

@@ -259,6 +259,16 @@ module BABYLON {
             return results;
         }
 
+        public getActiveTextures(): BaseTexture[] {
+            var activeTextures = super.getActiveTextures();
+
+            if (this._diffuseTexture) {
+                activeTextures.push(this._diffuseTexture);
+            }
+
+            return activeTextures;
+        }
+
         public dispose(forceDisposeEffect?: boolean): void {
             if (this._diffuseTexture) {
                 this._diffuseTexture.dispose();

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

@@ -332,6 +332,40 @@ module BABYLON {
             return results;
         }
 
+        public getActiveTextures(): BaseTexture[] {
+            var activeTextures = super.getActiveTextures();
+
+            if (this._mixTexture) {
+                activeTextures.push(this._mixTexture);
+            }
+
+            if (this._diffuseTexture1) {
+                activeTextures.push(this._diffuseTexture1);
+            }
+
+            if (this._diffuseTexture2) {
+                activeTextures.push(this._diffuseTexture2);
+            }
+
+            if (this._diffuseTexture3) {
+                activeTextures.push(this._diffuseTexture3);
+            }
+
+            if (this._bumpTexture1) {
+                activeTextures.push(this._bumpTexture1);
+            }
+
+            if (this._bumpTexture2) {
+                activeTextures.push(this._bumpTexture2);
+            }
+
+            if (this._bumpTexture3) {
+                activeTextures.push(this._bumpTexture3);
+            }
+
+            return activeTextures;
+        }
+
         public dispose(forceDisposeEffect?: boolean): void {
             if (this.mixTexture) {
                 this.mixTexture.dispose();

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

@@ -332,6 +332,36 @@ module BABYLON {
             return results;
         }
 
+        public getActiveTextures(): BaseTexture[] {
+            var activeTextures = super.getActiveTextures();
+
+            if (this._diffuseTextureX) {
+                activeTextures.push(this._diffuseTextureX);
+            }
+
+            if (this._diffuseTextureY) {
+                activeTextures.push(this._diffuseTextureY);
+            }
+
+            if (this._diffuseTextureZ) {
+                activeTextures.push(this._diffuseTextureZ);
+            }
+
+            if (this._normalTextureX) {
+                activeTextures.push(this._normalTextureX);
+            }
+
+            if (this._normalTextureY) {
+                activeTextures.push(this._normalTextureY);
+            }
+
+            if (this._normalTextureZ) {
+                activeTextures.push(this._normalTextureZ);
+            }
+
+            return activeTextures;
+        }
+
         public dispose(forceDisposeEffect?: boolean): void {
             if (this.mixTexture) {
                 this.mixTexture.dispose();

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

@@ -548,6 +548,16 @@ module BABYLON {
             return results;
         }
 
+        public getActiveTextures(): BaseTexture[] {
+            var activeTextures = super.getActiveTextures();
+
+            if (this._bumpTexture) {
+                activeTextures.push(this._bumpTexture);
+            }
+
+            return activeTextures;
+        }
+
         public dispose(forceDisposeEffect?: boolean): void {
             if (this.bumpTexture) {
                 this.bumpTexture.dispose();

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

@@ -109,7 +109,7 @@
      * For more information, please refer to the documentation : 
      * http://doc.babylonjs.com/extensions/Physically_Based_Rendering
      */
-    export abstract class PBRBaseMaterial extends BABYLON.PushMaterial {
+    export abstract class PBRBaseMaterial extends PushMaterial {
 
         /**
          * Intensity of the direct lights e.g. the four lights available in your scene.
@@ -458,6 +458,10 @@
         }
 
         public needAlphaTesting(): boolean {
+            if (this._forceAlphaTest) {
+                return true;
+            }
+
             if (this._linkRefractionWithTransparency) {
                 return false;
             }

+ 50 - 0
src/Materials/PBR/babylon.pbrMaterial.ts

@@ -530,6 +530,56 @@
             return "PBRMaterial";
         }
 
+        public getActiveTextures(): BaseTexture[] {
+            var activeTextures = super.getActiveTextures();
+
+            if (this._albedoTexture) {
+                activeTextures.push(this._albedoTexture);
+            }
+
+            if (this._ambientTexture) {
+                activeTextures.push(this._ambientTexture);
+            }
+
+            if (this._opacityTexture) {
+                activeTextures.push(this._opacityTexture);
+            }
+
+            if (this._reflectionTexture) {
+                activeTextures.push(this._reflectionTexture);
+            }
+
+            if (this._emissiveTexture) {
+                activeTextures.push(this._emissiveTexture);
+            }
+
+            if (this._reflectionTexture) {
+                activeTextures.push(this._reflectionTexture);
+            }
+
+            if (this._metallicTexture) {
+                activeTextures.push(this._metallicTexture);
+            }
+
+            if (this._microSurfaceTexture) {
+                activeTextures.push(this._microSurfaceTexture);
+            }
+
+            if (this._bumpTexture) {
+                activeTextures.push(this._bumpTexture);
+            }
+
+            if (this._lightmapTexture) {
+                activeTextures.push(this._lightmapTexture);
+            }
+
+            if (this._refractionTexture) {
+                activeTextures.push(this._refractionTexture);
+            }
+
+            return activeTextures;
+        }
+
         public clone(name: string): PBRMaterial {
             return SerializationHelper.Clone(() => new PBRMaterial(name, this.getScene()), this);
         }

+ 17 - 0
src/Materials/PBR/babylon.pbrMetallicRoughnessMaterial.ts

@@ -69,6 +69,23 @@
         }
 
         /**
+         * Return the active textures of the material.
+         */
+        public getActiveTextures(): BaseTexture[] {
+            var activeTextures = super.getActiveTextures();
+
+            if (this.baseTexture) {
+                activeTextures.push(this.baseTexture);
+            }
+
+            if (this.metallicRoughnessTexture) {
+                activeTextures.push(this.metallicRoughnessTexture);
+            }
+
+            return activeTextures;
+        }
+
+        /**
          * Serialize the material to a parsable JSON object.
          */
         public serialize(): any {

+ 17 - 0
src/Materials/PBR/babylon.pbrSpecularGlossinessMaterial.ts

@@ -62,6 +62,23 @@
         }
 
         /**
+         * Return the active textures of the material.
+         */
+        public getActiveTextures(): BaseTexture[] {
+            var activeTextures = super.getActiveTextures();
+
+            if (this.diffuseTexture) {
+                activeTextures.push(this.diffuseTexture);
+            }
+
+            if (this.specularGlossinessTexture) {
+                activeTextures.push(this.specularGlossinessTexture);
+            }
+
+            return activeTextures;
+        }
+
+        /**
          * Serialize the material to a parsable JSON object.
          */
         public serialize(): any {

+ 41 - 0
src/Materials/Textures/babylon.baseTexture.ts

@@ -198,6 +198,21 @@
             return null;
         }
 
+        public readPixels(faceIndex = 0): Uint8Array {
+            if (!this._texture) {
+                return null;
+            }
+
+            var size = this.getSize();
+            var engine = this.getScene().getEngine();
+
+            if (this._texture.isCube) {
+                return engine._readTexturePixels(this._texture, size.width, size.height, faceIndex);
+            }
+
+            return engine._readTexturePixels(this._texture, size.width, size.height);
+        }
+
         public releaseInternalTexture(): void {
             if (this._texture) {
                 this._scene.getEngine().releaseInternalTexture(this._texture);
@@ -241,5 +256,31 @@
 
             return serializationObject;
         }
+
+        public static WhenAllReady(textures: BaseTexture[], onLoad: () => void): void {
+            var numReady = 0;
+
+            for (var i = 0; i < textures.length; i++) {
+                var texture = textures[i];
+
+                if (texture.isReady()) {
+                    if (++numReady === textures.length) {
+                        onLoad();
+                    }
+                }
+                else {
+                    var observable = (texture as any).onLoadObservable as Observable<Texture>;
+
+                    let callback = () => {
+                        observable.removeCallback(callback);
+                        if (++numReady === textures.length) {
+                            onLoad();
+                        }
+                    };
+
+                    observable.add(callback);
+                }
+            }
+        }
     }
 } 

+ 7 - 7
src/Materials/Textures/babylon.texture.ts

@@ -72,7 +72,7 @@
         protected _format: number;
         private _delayedOnLoad: () => void;
         private _delayedOnError: () => void;
-        private _onLoadObservarble: Observable<boolean>;
+        private _onLoadObservable: Observable<Texture>;
 
         protected _isBlocking: boolean = true;
         public set isBlocking(value: boolean) {
@@ -98,8 +98,8 @@
             scene = this.getScene();
 
             let load = () => {
-                if (this._onLoadObservarble && this._onLoadObservarble.hasObservers()) {
-                    this.onLoadObservable.notifyObservers(true);
+                if (this._onLoadObservable && this._onLoadObservable.hasObservers()) {
+                    this.onLoadObservable.notifyObservers(this);
                 }
                 if (onLoad) {
                     onLoad();
@@ -287,11 +287,11 @@
             }, this);
         }
 
-        public get onLoadObservable(): Observable<boolean> {
-            if (!this._onLoadObservarble) {
-                this._onLoadObservarble = new Observable<boolean>();
+        public get onLoadObservable(): Observable<Texture> {
+            if (!this._onLoadObservable) {
+                this._onLoadObservable = new Observable<Texture>();
             }
-            return this._onLoadObservarble;
+            return this._onLoadObservable;
         }
 
         // Statics

+ 12 - 2
src/Materials/babylon.material.ts

@@ -482,6 +482,10 @@
             }
         }
 
+        public getActiveTextures(): BaseTexture[] {
+            return [];
+        }
+
         public clone(name: string): Material {
             return null;
         }
@@ -501,15 +505,19 @@
         }
 
         // Force shader compilation including textures ready check
-        public forceCompilation(mesh: AbstractMesh, onCompiled: (material: Material) => void): void {
+        public forceCompilation(mesh: AbstractMesh, onCompiled: (material: Material) => void, options?: { alphaTest: boolean }): void {
             var subMesh = new BaseSubMesh();
             var scene = this.getScene();
+            var engine = scene.getEngine();
 
             var beforeRenderCallback = () => {
                 if (subMesh._materialDefines) {
                     subMesh._materialDefines._renderId = -1;
                 }
-
+                
+                var alphaTestState = engine.getAlphaTesting();
+                engine.setAlphaTesting(options ? options.alphaTest : this.needAlphaTesting());
+                
                 if (this.isReadyForSubMesh(mesh, subMesh)) {
                     scene.unregisterBeforeRender(beforeRenderCallback);
 
@@ -517,6 +525,8 @@
                         onCompiled(this);
                     }
                 }
+
+                engine.setAlphaTesting(alphaTestState);
             };
 
             scene.registerBeforeRender(beforeRenderCallback);

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

@@ -169,6 +169,11 @@
             for (var index = lightIndex; index < maxSimultaneousLights; index++) {
                 if (defines["LIGHT" + index] !== undefined) {
                     defines["LIGHT" + index] = false;
+                    defines["HEMILIGHT" + lightIndex] = false;
+                    defines["POINTLIGHT" + lightIndex] = false;
+                    defines["DIRLIGHT" + lightIndex] = false;                    
+                    defines["SPOTLIGHT" + lightIndex] = false;
+                    defines["SHADOW" + lightIndex] = false;
                 }
             }
 

+ 0 - 0
src/Materials/babylon.multiMaterial.ts


Деякі файли не було показано, через те що забагато файлів було змінено