Prechádzať zdrojové kódy

Merge remote-tracking branch 'upstream/master'

# Conflicts:
#	dist/preview release/babylon.d.ts
#	dist/preview release/babylon.js
#	dist/preview release/babylon.worker.js
#	dist/preview release/viewer/babylon.viewer.js
Rémi Louvat 7 rokov pred
rodič
commit
ab429c97f0
66 zmenil súbory, kde vykonal 19533 pridanie a 18131 odobranie
  1. 1971 1879
      Playground/babylon.d.txt
  2. 5 0
      Tools/Gulp/config.json
  3. BIN
      assets/environments/fullFloatEnvironmentBrdf.dds
  4. 15590 15549
      dist/preview release/babylon.d.ts
  5. 22 22
      dist/preview release/babylon.js
  6. 74 17
      dist/preview release/babylon.max.js
  7. 74 17
      dist/preview release/babylon.no-module.max.js
  8. 22 22
      dist/preview release/babylon.worker.js
  9. 74 17
      dist/preview release/es6.js
  10. 1 1
      dist/preview release/gltf2Interface/package.json
  11. 6 0
      dist/preview release/gui/babylon.gui.d.ts
  12. 11 0
      dist/preview release/gui/babylon.gui.js
  13. 4 4
      dist/preview release/gui/babylon.gui.min.js
  14. 6 0
      dist/preview release/gui/babylon.gui.module.d.ts
  15. 1 1
      dist/preview release/gui/package.json
  16. 5 4
      dist/preview release/inspector/babylon.inspector.bundle.js
  17. 30 0
      dist/preview release/inspector/babylon.inspector.css
  18. 11 0
      dist/preview release/inspector/babylon.inspector.d.ts
  19. 63 1
      dist/preview release/inspector/babylon.inspector.js
  20. 4 4
      dist/preview release/inspector/babylon.inspector.min.js
  21. 1 1
      dist/preview release/inspector/package.json
  22. 29 10
      dist/preview release/loaders/babylon.glTF1FileLoader.d.ts
  23. 16 4
      dist/preview release/loaders/babylon.glTF1FileLoader.js
  24. 2 2
      dist/preview release/loaders/babylon.glTF1FileLoader.min.js
  25. 54 9
      dist/preview release/loaders/babylon.glTF2FileLoader.d.ts
  26. 186 46
      dist/preview release/loaders/babylon.glTF2FileLoader.js
  27. 2 2
      dist/preview release/loaders/babylon.glTF2FileLoader.min.js
  28. 63 19
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  29. 189 54
      dist/preview release/loaders/babylon.glTFFileLoader.js
  30. 3 3
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  31. 63 19
      dist/preview release/loaders/babylonjs.loaders.d.ts
  32. 171 54
      dist/preview release/loaders/babylonjs.loaders.js
  33. 4 4
      dist/preview release/loaders/babylonjs.loaders.min.js
  34. 63 19
      dist/preview release/loaders/babylonjs.loaders.module.d.ts
  35. 2 2
      dist/preview release/loaders/package.json
  36. 1 1
      dist/preview release/materialsLibrary/package.json
  37. 1 1
      dist/preview release/postProcessesLibrary/package.json
  38. 1 1
      dist/preview release/proceduralTexturesLibrary/package.json
  39. 2 2
      dist/preview release/serializers/package.json
  40. 2 136
      dist/preview release/typedocValidationBaseline.json
  41. 32 32
      dist/preview release/viewer/babylon.viewer.js
  42. 245 71
      dist/preview release/viewer/babylon.viewer.max.js
  43. 1 1
      dist/preview release/viewer/package.json
  44. 2 1
      dist/preview release/what's new.md
  45. 9 0
      gui/src/controls/control.ts
  46. 1 0
      inspector/sass/main.scss
  47. 45 0
      inspector/sass/tabs/_gltfTab.scss
  48. 53 0
      inspector/src/tabs/GLTFTab.ts
  49. 1 1
      inspector/src/tabs/PropertyTab.ts
  50. 3 1
      inspector/src/tabs/TabBar.ts
  51. 9 10
      loaders/src/glTF/1.0/babylon.glTFLoader.ts
  52. 1 1
      loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts
  53. 1 1
      loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts
  54. 36 0
      loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts
  55. 36 0
      loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts
  56. 70 57
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  57. 28 0
      loaders/src/glTF/babylon.glTFFileLoader.ts
  58. 1 1
      package.json
  59. 8 1
      src/Engine/babylon.engine.ts
  60. 3 2
      src/Loading/babylon.sceneLoader.ts
  61. 2 2
      src/Materials/PBR/babylon.pbrBaseMaterial.ts
  62. 4 2
      src/Materials/Textures/babylon.videoTexture.ts
  63. 3 5
      src/Shaders/ShadersInclude/pbrFunctions.fx
  64. 6 6
      src/Shaders/pbr.fragment.fx
  65. 56 9
      src/Tools/babylon.database.ts
  66. 48 0
      tests/unit/babylon/src/Loading/babylon.sceneLoader.tests.ts

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1971 - 1879
Playground/babylon.d.txt


+ 5 - 0
Tools/Gulp/config.json

@@ -1533,6 +1533,8 @@
                     "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_lod.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts",
@@ -1555,6 +1557,8 @@
                     "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
                     "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_lod.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts",
@@ -1700,6 +1704,7 @@
                     "../../inspector/src/tabs/SceneTab.ts",
                     "../../inspector/src/tabs/ConsoleTab.ts",
                     "../../inspector/src/tabs/StatsTab.ts",
+                    "../../inspector/src/tabs/GLTFTab.ts",
                     "../../inspector/src/tabs/TabBar.ts",
                     "../../inspector/src/tools/AbstractTool.ts",
                     "../../inspector/src/tools/PauseScheduleTool.ts",

BIN
assets/environments/fullFloatEnvironmentBrdf.dds


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 15590 - 15549
dist/preview release/babylon.d.ts


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 22 - 22
dist/preview release/babylon.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 74 - 17
dist/preview release/babylon.max.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 74 - 17
dist/preview release/babylon.no-module.max.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 22 - 22
dist/preview release/babylon.worker.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 74 - 17
dist/preview release/es6.js


+ 1 - 1
dist/preview release/gltf2Interface/package.json

@@ -1,7 +1,7 @@
 {
     "name": "babylonjs-gltf2interface",
     "description": "A typescript declaration of babylon's gltf2 inteface.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

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

@@ -268,6 +268,12 @@ declare module BABYLON.GUI {
        * An event triggered after the control is drawn
        */
         onAfterDrawObservable: Observable<Control>;
+        /** Gets or set information about font offsets (used to render and align text) */
+        fontOffset: {
+            ascent: number;
+            height: number;
+            descent: number;
+        };
         alpha: number;
         scaleX: number;
         scaleY: number;

+ 11 - 0
dist/preview release/gui/babylon.gui.js

@@ -1081,6 +1081,17 @@ var BABYLON;
                 enumerable: true,
                 configurable: true
             });
+            Object.defineProperty(Control.prototype, "fontOffset", {
+                /** Gets or set information about font offsets (used to render and align text) */
+                get: function () {
+                    return this._fontOffset;
+                },
+                set: function (offset) {
+                    this._fontOffset = offset;
+                },
+                enumerable: true,
+                configurable: true
+            });
             Object.defineProperty(Control.prototype, "alpha", {
                 get: function () {
                     return this._alpha;

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 4 - 4
dist/preview release/gui/babylon.gui.min.js


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

@@ -273,6 +273,12 @@ declare module BABYLON.GUI {
        * An event triggered after the control is drawn
        */
         onAfterDrawObservable: Observable<Control>;
+        /** Gets or set information about font offsets (used to render and align text) */
+        fontOffset: {
+            ascent: number;
+            height: number;
+            descent: number;
+        };
         alpha: number;
         scaleX: number;
         scaleY: number;

+ 1 - 1
dist/preview release/gui/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-gui",
     "description": "The Babylon.js GUI library is an extension you can use to generate interactive user interface. It is build on top of the DynamicTexture.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 5 - 4
dist/preview release/inspector/babylon.inspector.bundle.js


+ 30 - 0
dist/preview release/inspector/babylon.inspector.css

@@ -242,6 +242,36 @@
   .insp-wrapper .tab-panel .stat-infos {
     width: 100%;
     padding: 4px; }
+  .insp-wrapper .tab-panel .gltf-actions {
+    overflow-y: auto;
+    padding-left: 5px; }
+    .insp-wrapper .tab-panel .gltf-actions .gltf-title {
+      font-size: 1.1em;
+      padding-bottom: 10px;
+      border-bottom: 1px solid #5db0d7;
+      margin: 10px 0 10px 0; }
+    .insp-wrapper .tab-panel .gltf-actions .gltf-input {
+      background-color: #2c2c2c;
+      border: none;
+      outline: none;
+      font-family: "Inconsolata", sans-serif;
+      color: #b3b3b3;
+      padding: 5px;
+      margin: 0px 6px 0px 0; }
+      .insp-wrapper .tab-panel .gltf-actions .gltf-input:hover {
+        background-color: #383838; }
+    .insp-wrapper .tab-panel .gltf-actions .gltf-button {
+      background-color: #2c2c2c;
+      border: none;
+      outline: none;
+      font-family: "Inconsolata", sans-serif;
+      color: #ccc;
+      padding: 5px 10px;
+      margin: 0px 6px 0px 0; }
+      .insp-wrapper .tab-panel .gltf-actions .gltf-button:hover {
+        background-color: #383838; }
+      .insp-wrapper .tab-panel .gltf-actions .gltf-button:active {
+        background-color: #454545; }
   .insp-wrapper .property-type {
     color: #5db0d7; }
   .insp-wrapper .property-name, .insp-wrapper .insp-details .base-row .prop-name, .insp-wrapper .insp-details .row .prop-name, .insp-wrapper .insp-details .header-row .prop-name {

+ 11 - 0
dist/preview release/inspector/babylon.inspector.d.ts

@@ -1017,6 +1017,17 @@ declare module INSPECTOR {
     }
 }
 
+
+
+declare module INSPECTOR {
+    class GLTFTab extends Tab {
+        constructor(tabbar: TabBar, inspector: Inspector);
+        dispose(): void;
+        private _addExport(inspector, actions);
+        private static _IsSkyBox(transformNode);
+    }
+}
+
 declare module INSPECTOR {
     /**
      * A tab bar will contains each view the inspector can have : Canvas2D, Meshes...

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

@@ -2801,7 +2801,7 @@ var INSPECTOR;
                     node.active(false);
                 }
             }
-            item.getDiv().scrollIntoView();
+            //  item.getDiv().scrollIntoView();
             item.active(true);
         };
         /** Returns the treeitem corersponding to the given obj, null if not found */
@@ -4021,6 +4021,65 @@ var INSPECTOR;
     INSPECTOR.StatsTab = StatsTab;
 })(INSPECTOR || (INSPECTOR = {}));
 
+/// <reference path="../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../dist/preview release/serializers/babylon.glTF2Serializer.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 INSPECTOR;
+(function (INSPECTOR) {
+    var GLTFTab = /** @class */ (function (_super) {
+        __extends(GLTFTab, _super);
+        function GLTFTab(tabbar, inspector) {
+            var _this = _super.call(this, tabbar, 'GLTF') || this;
+            _this._panel = INSPECTOR.Helpers.CreateDiv('tab-panel');
+            var actions = INSPECTOR.Helpers.CreateDiv('gltf-actions', _this._panel);
+            _this._addExport(inspector, actions);
+            return _this;
+        }
+        GLTFTab.prototype.dispose = function () {
+            // Nothing to dispose
+        };
+        GLTFTab.prototype._addExport = function (inspector, actions) {
+            var title = INSPECTOR.Helpers.CreateDiv('gltf-title', actions);
+            title.textContent = 'Export';
+            var name = INSPECTOR.Helpers.CreateInput('gltf-input', actions);
+            name.placeholder = "File name...";
+            var button = INSPECTOR.Helpers.CreateElement('button', 'gltf-button', actions);
+            button.innerText = 'Export GLB';
+            button.addEventListener('click', function () {
+                var data = BABYLON.GLTF2Export.GLB(inspector.scene, name.value || "scene", {
+                    shouldExportMesh: function (mesh) { return !GLTFTab._IsSkyBox(mesh); }
+                });
+                if (data) {
+                    data.downloadFiles();
+                }
+            });
+        };
+        GLTFTab._IsSkyBox = function (transformNode) {
+            if (transformNode instanceof BABYLON.Mesh) {
+                if (transformNode.material) {
+                    var material = transformNode.material;
+                    var reflectionTexture = material.reflectionTexture;
+                    if (reflectionTexture && reflectionTexture.coordinatesMode === BABYLON.Texture.SKYBOX_MODE) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        };
+        return GLTFTab;
+    }(INSPECTOR.Tab));
+    INSPECTOR.GLTFTab = GLTFTab;
+})(INSPECTOR || (INSPECTOR = {}));
+
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = Object.setPrototypeOf ||
         ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
@@ -4056,6 +4115,9 @@ var INSPECTOR;
             _this._tabs.push(_this._meshTab);
             _this._tabs.push(new INSPECTOR.LightTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.MaterialTab(_this, _this._inspector));
+            if (BABYLON.GLTF2Export) {
+                _this._tabs.push(new INSPECTOR.GLTFTab(_this, _this._inspector));
+            }
             if (BABYLON.GUI) {
                 _this._tabs.push(new INSPECTOR.GUITab(_this, _this._inspector));
             }

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 4 - 4
dist/preview release/inspector/babylon.inspector.min.js


+ 1 - 1
dist/preview release/inspector/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-inspector",
     "description": "The Babylon.js inspector.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 29 - 10
dist/preview release/loaders/babylon.glTF1FileLoader.d.ts

@@ -98,6 +98,16 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -199,6 +209,16 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -743,16 +763,15 @@ declare module BABYLON.GLTF1 {
         compileMaterials: boolean;
         useClipPlane: boolean;
         compileShadowGenerators: boolean;
-        onDisposeObservable: Observable<IGLTFLoader>;
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-        onTextureLoadedObservable: Observable<BaseTexture>;
-        onMaterialLoadedObservable: Observable<Material>;
-        onCameraLoadedObservable: Observable<Camera>;
-        onCompleteObservable: Observable<IGLTFLoader>;
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
-        * State of the loader
-        */
+        transparencyAsCoverage: boolean;
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
+        readonly onTextureLoadedObservable: Observable<BaseTexture>;
+        readonly onMaterialLoadedObservable: Observable<Material>;
+        readonly onCameraLoadedObservable: Observable<Camera>;
+        readonly onCompleteObservable: Observable<IGLTFLoader>;
+        readonly onDisposeObservable: Observable<IGLTFLoader>;
+        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         state: Nullable<GLTFLoaderState>;
         dispose(): void;
         private _importMeshAsync(meshesNames, scene, data, rootUrl, onSuccess, onProgress?, onError?);

+ 16 - 4
dist/preview release/loaders/babylon.glTF1FileLoader.js

@@ -84,6 +84,16 @@ var BABYLON;
              */
             this.compileShadowGenerators = false;
             /**
+             * Defines if the Alpha blended materials are only applied as coverage.
+             * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+             * If true, no extra effects are applied to transparent pixels.
+             */
+            this.transparencyAsCoverage = false;
+            /**
+             * Function called before loading a url referenced by the asset.
+             */
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+            /**
              * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
              */
             this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -262,6 +272,7 @@ var BABYLON;
                 this._loader.dispose();
                 this._loader = null;
             }
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
@@ -389,6 +400,8 @@ var BABYLON;
             loader.compileMaterials = this.compileMaterials;
             loader.useClipPlane = this.useClipPlane;
             loader.compileShadowGenerators = this.compileShadowGenerators;
+            loader.transparencyAsCoverage = this.transparencyAsCoverage;
+            loader.preprocessUrlAsync = this.preprocessUrlAsync;
             loader.onMeshLoadedObservable.add(function (mesh) { return _this.onMeshLoadedObservable.notifyObservers(mesh); });
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
@@ -1968,16 +1981,15 @@ var BABYLON;
                 this.compileMaterials = false;
                 this.useClipPlane = false;
                 this.compileShadowGenerators = false;
-                this.onDisposeObservable = new BABYLON.Observable();
+                this.transparencyAsCoverage = false;
+                this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
                 this.onMeshLoadedObservable = new BABYLON.Observable();
                 this.onTextureLoadedObservable = new BABYLON.Observable();
                 this.onMaterialLoadedObservable = new BABYLON.Observable();
                 this.onCameraLoadedObservable = new BABYLON.Observable();
                 this.onCompleteObservable = new BABYLON.Observable();
+                this.onDisposeObservable = new BABYLON.Observable();
                 this.onExtensionLoadedObservable = new BABYLON.Observable();
-                /**
-                * State of the loader
-                */
                 this.state = null;
             }
             GLTFLoader.RegisterExtension = function (extension) {

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


+ 54 - 9
dist/preview release/loaders/babylon.glTF2FileLoader.d.ts

@@ -98,6 +98,16 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -199,6 +209,16 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -471,11 +491,6 @@ declare module BABYLON.GLTF2 {
  * Defines the module used to import/export glTF 2.0 assets
  */
 declare module BABYLON.GLTF2 {
-    /** @hidden */
-    interface _MaterialConstructor<T extends Material> {
-        readonly prototype: T;
-        new (name: string, scene: Scene): T;
-    }
     /**
      * Loader for loading a glTF 2.0 asset
      */
@@ -495,8 +510,8 @@ declare module BABYLON.GLTF2 {
         private _defaultBabylonMaterials;
         private _progressCallback?;
         private _requests;
-        private static _Names;
-        private static _Factories;
+        private static _ExtensionNames;
+        private static _ExtensionFactories;
         /** @hidden */
         static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void;
         /**
@@ -520,6 +535,16 @@ declare module BABYLON.GLTF2 {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -583,9 +608,9 @@ declare module BABYLON.GLTF2 {
          */
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
         private _loadAsync(nodes, scene, data, rootUrl, onProgress?);
-        private _loadExtensions();
         private _loadData(data);
         private _setupData();
+        private _loadExtensions();
         private _checkExtensions();
         private _createRootNode();
         private _loadNodesAsync(nodes);
@@ -629,7 +654,7 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void>;
         /** @hidden */
-        _createMaterial<T extends Material>(type: _MaterialConstructor<T>, name: string, drawMode: number): T;
+        _createMaterial(name: string, drawMode: number): PBRMaterial;
         /** @hidden */
         _loadMaterialBasePropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void>;
         /** @hidden */
@@ -725,6 +750,26 @@ declare module BABYLON.GLTF2.Extensions {
 
 
 declare module BABYLON.GLTF2.Extensions {
+    /** @hidden */
+    class MSFT_minecraftMesh extends GLTFLoaderExtension {
+        readonly name: string;
+        constructor(loader: GLTFLoader);
+        private _onMaterialLoaded;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    /** @hidden */
+    class MSFT_sRGBFactors extends GLTFLoaderExtension {
+        readonly name: string;
+        constructor(loader: GLTFLoader);
+        private _onMaterialLoaded;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
     /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression)
      */

+ 186 - 46
dist/preview release/loaders/babylon.glTF2FileLoader.js

@@ -84,6 +84,16 @@ var BABYLON;
              */
             this.compileShadowGenerators = false;
             /**
+             * Defines if the Alpha blended materials are only applied as coverage.
+             * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+             * If true, no extra effects are applied to transparent pixels.
+             */
+            this.transparencyAsCoverage = false;
+            /**
+             * Function called before loading a url referenced by the asset.
+             */
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+            /**
              * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
              */
             this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -262,6 +272,7 @@ var BABYLON;
                 this._loader.dispose();
                 this._loader = null;
             }
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
@@ -389,6 +400,8 @@ var BABYLON;
             loader.compileMaterials = this.compileMaterials;
             loader.useClipPlane = this.useClipPlane;
             loader.compileShadowGenerators = this.compileShadowGenerators;
+            loader.transparencyAsCoverage = this.transparencyAsCoverage;
+            loader.preprocessUrlAsync = this.preprocessUrlAsync;
             loader.onMeshLoadedObservable.add(function (mesh) { return _this.onMeshLoadedObservable.notifyObservers(mesh); });
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
@@ -648,6 +661,16 @@ var BABYLON;
                  */
                 this.compileShadowGenerators = false;
                 /**
+                 * Defines if the Alpha blended materials are only applied as coverage.
+                 * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+                 * If true, no extra effects are applied to transparent pixels.
+                 */
+                this.transparencyAsCoverage = false;
+                /**
+                 * Function called before loading a url referenced by the asset.
+                 */
+                this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+                /**
                  * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
                  */
                 this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -681,13 +704,13 @@ var BABYLON;
             }
             /** @hidden */
             GLTFLoader._Register = function (name, factory) {
-                if (GLTFLoader._Factories[name]) {
+                if (GLTFLoader._ExtensionFactories[name]) {
                     BABYLON.Tools.Error("Extension with the name '" + name + "' already exists");
                     return;
                 }
-                GLTFLoader._Factories[name] = factory;
+                GLTFLoader._ExtensionFactories[name] = factory;
                 // Keep the order of registration so that extensions registered first are called first.
-                GLTFLoader._Names.push(name);
+                GLTFLoader._ExtensionNames.push(name);
             };
             Object.defineProperty(GLTFLoader.prototype, "state", {
                 /**
@@ -767,12 +790,12 @@ var BABYLON;
             GLTFLoader.prototype._loadAsync = function (nodes, scene, data, rootUrl, onProgress) {
                 var _this = this;
                 return Promise.resolve().then(function () {
-                    _this._loadExtensions();
                     _this._babylonScene = scene;
                     _this._rootUrl = rootUrl;
                     _this._progressCallback = onProgress;
                     _this._state = BABYLON.GLTFLoaderState.LOADING;
                     _this._loadData(data);
+                    _this._loadExtensions();
                     _this._checkExtensions();
                     var promises = new Array();
                     if (nodes) {
@@ -810,20 +833,13 @@ var BABYLON;
                     });
                     return resultPromise;
                 }).catch(function (error) {
-                    BABYLON.Tools.Error("glTF Loader: " + error.message);
-                    _this._clear();
-                    throw error;
+                    if (!_this._disposed) {
+                        BABYLON.Tools.Error("glTF Loader: " + error.message);
+                        _this._clear();
+                        throw error;
+                    }
                 });
             };
-            GLTFLoader.prototype._loadExtensions = function () {
-                for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
-                    var name_1 = _a[_i];
-                    var extension = GLTFLoader._Factories[name_1](this);
-                    this._extensions[name_1] = extension;
-                    this.onExtensionLoadedObservable.notifyObservers(extension);
-                }
-                this.onExtensionLoadedObservable.clear();
-            };
             GLTFLoader.prototype._loadData = function (data) {
                 this._gltf = data.json;
                 this._setupData();
@@ -874,6 +890,15 @@ var BABYLON;
                     }
                 }
             };
+            GLTFLoader.prototype._loadExtensions = function () {
+                for (var _i = 0, _a = GLTFLoader._ExtensionNames; _i < _a.length; _i++) {
+                    var name_1 = _a[_i];
+                    var extension = GLTFLoader._ExtensionFactories[name_1](this);
+                    this._extensions[name_1] = extension;
+                    this.onExtensionLoadedObservable.notifyObservers(extension);
+                }
+                this.onExtensionLoadedObservable.clear();
+            };
             GLTFLoader.prototype._checkExtensions = function () {
                 if (this._gltf.extensionsRequired) {
                     for (var _i = 0, _a = this._gltf.extensionsRequired; _i < _a.length; _i++) {
@@ -1687,7 +1712,7 @@ var BABYLON;
             GLTFLoader.prototype._getDefaultMaterial = function (drawMode) {
                 var babylonMaterial = this._defaultBabylonMaterials[drawMode];
                 if (!babylonMaterial) {
-                    babylonMaterial = this._createMaterial(BABYLON.PBRMaterial, "__gltf_default", drawMode);
+                    babylonMaterial = this._createMaterial("__gltf_default", drawMode);
                     babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE;
                     babylonMaterial.metallic = 1;
                     babylonMaterial.roughness = 1;
@@ -1739,7 +1764,7 @@ var BABYLON;
                 if (!babylonData) {
                     var promises = new Array();
                     var name_3 = material.name || "materialSG_" + material._index;
-                    var babylonMaterial = this._createMaterial(BABYLON.PBRMaterial, name_3, babylonDrawMode);
+                    var babylonMaterial = this._createMaterial(name_3, babylonDrawMode);
                     promises.push(this._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                     promises.push(this._loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial));
                     this.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
@@ -1755,10 +1780,13 @@ var BABYLON;
                 return babylonData.loaded;
             };
             /** @hidden */
-            GLTFLoader.prototype._createMaterial = function (type, name, drawMode) {
-                var babylonMaterial = new type(name, this._babylonScene);
+            GLTFLoader.prototype._createMaterial = function (name, drawMode) {
+                var babylonMaterial = new BABYLON.PBRMaterial(name, this._babylonScene);
                 babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? BABYLON.Material.CounterClockWiseSideOrientation : BABYLON.Material.ClockWiseSideOrientation;
                 babylonMaterial.fillMode = drawMode;
+                babylonMaterial.enableSpecularAntiAliasing = true;
+                babylonMaterial.useRadianceOverAlpha = !this.transparencyAsCoverage;
+                babylonMaterial.useSpecularOverAlpha = !this.transparencyAsCoverage;
                 return babylonMaterial;
             };
             /** @hidden */
@@ -1897,31 +1925,35 @@ var BABYLON;
                 if (BABYLON.Tools.IsBase64(uri)) {
                     return Promise.resolve(new Uint8Array(BABYLON.Tools.DecodeBase64(uri)));
                 }
-                return new Promise(function (resolve, reject) {
-                    var request = BABYLON.Tools.LoadFile(_this._rootUrl + uri, function (data) {
+                return this.preprocessUrlAsync(this._rootUrl + uri).then(function (url) {
+                    return new Promise(function (resolve, reject) {
                         if (!_this._disposed) {
-                            resolve(new Uint8Array(data));
-                        }
-                    }, function (event) {
-                        if (!_this._disposed) {
-                            try {
-                                if (request && _this._state === BABYLON.GLTFLoaderState.LOADING) {
-                                    request._lengthComputable = event.lengthComputable;
-                                    request._loaded = event.loaded;
-                                    request._total = event.total;
-                                    _this._onProgress();
+                            var request_1 = BABYLON.Tools.LoadFile(url, function (data) {
+                                if (!_this._disposed) {
+                                    resolve(new Uint8Array(data));
                                 }
-                            }
-                            catch (e) {
-                                reject(e);
-                            }
-                        }
-                    }, _this._babylonScene.database, true, function (request, exception) {
-                        if (!_this._disposed) {
-                            reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
+                            }, function (event) {
+                                if (!_this._disposed) {
+                                    try {
+                                        if (request_1 && _this._state === BABYLON.GLTFLoaderState.LOADING) {
+                                            request_1._lengthComputable = event.lengthComputable;
+                                            request_1._loaded = event.loaded;
+                                            request_1._total = event.total;
+                                            _this._onProgress();
+                                        }
+                                    }
+                                    catch (e) {
+                                        reject(e);
+                                    }
+                                }
+                            }, _this._babylonScene.database, true, function (request, exception) {
+                                if (!_this._disposed) {
+                                    reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
+                                }
+                            });
+                            _this._requests.push(request_1);
                         }
                     });
-                    _this._requests.push(request);
                 });
             };
             GLTFLoader.prototype._onProgress = function () {
@@ -2112,7 +2144,7 @@ var BABYLON;
             };
             /** @hidden */
             GLTFLoader.prototype._applyExtensions = function (actionAsync) {
-                for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
+                for (var _i = 0, _a = GLTFLoader._ExtensionNames; _i < _a.length; _i++) {
                     var name_5 = _a[_i];
                     var extension = this._extensions[name_5];
                     if (extension.enabled) {
@@ -2124,8 +2156,8 @@ var BABYLON;
                 }
                 return null;
             };
-            GLTFLoader._Names = new Array();
-            GLTFLoader._Factories = {};
+            GLTFLoader._ExtensionNames = new Array();
+            GLTFLoader._ExtensionFactories = {};
             return GLTFLoader;
         }());
         GLTF2.GLTFLoader = GLTFLoader;
@@ -2400,6 +2432,114 @@ var BABYLON;
     (function (GLTF2) {
         var Extensions;
         (function (Extensions) {
+            var NAME = "MSFT_minecraftMesh";
+            /** @hidden */
+            var MSFT_minecraftMesh = /** @class */ (function (_super) {
+                __extends(MSFT_minecraftMesh, _super);
+                function MSFT_minecraftMesh(loader) {
+                    var _this = _super.call(this, loader) || this;
+                    _this.name = NAME;
+                    _this._onMaterialLoaded = function (material) {
+                        if (material.needAlphaBlending()) {
+                            material.forceDepthWrite = true;
+                            material.separateCullingPass = true;
+                        }
+                        material.backFaceCulling = material.forceDepthWrite;
+                        material.twoSidedLighting = true;
+                    };
+                    var meshes = loader._gltf.meshes;
+                    if (meshes && meshes.length) {
+                        for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                            var mesh = meshes_1[_i];
+                            if (mesh && mesh.extras && mesh.extras.MSFT_minecraftMesh) {
+                                _this._loader.onMaterialLoadedObservable.add(_this._onMaterialLoaded);
+                                break;
+                            }
+                        }
+                    }
+                    return _this;
+                }
+                return MSFT_minecraftMesh;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.MSFT_minecraftMesh = MSFT_minecraftMesh;
+            GLTF2.GLTFLoader._Register(NAME, function (loader) { return new MSFT_minecraftMesh(loader); });
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=MSFT_minecraftMesh.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 NAME = "MSFT_sRGBFactors";
+            /** @hidden */
+            var MSFT_sRGBFactors = /** @class */ (function (_super) {
+                __extends(MSFT_sRGBFactors, _super);
+                function MSFT_sRGBFactors(loader) {
+                    var _this = _super.call(this, loader) || this;
+                    _this.name = NAME;
+                    _this._onMaterialLoaded = function (material) {
+                        if (!material.albedoTexture) {
+                            material.albedoColor.toLinearSpaceToRef(material.albedoColor);
+                        }
+                        if (!material.reflectivityTexture) {
+                            material.reflectivityColor.toLinearSpaceToRef(material.reflectivityColor);
+                        }
+                    };
+                    var materials = loader._gltf.materials;
+                    if (materials && materials.length) {
+                        for (var _i = 0, materials_1 = materials; _i < materials_1.length; _i++) {
+                            var material = materials_1[_i];
+                            if (material && material.extras && material.extras.MSFT_sRGBFactors) {
+                                _this._loader.onMaterialLoadedObservable.add(_this._onMaterialLoaded);
+                                break;
+                            }
+                        }
+                    }
+                    return _this;
+                }
+                return MSFT_sRGBFactors;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.MSFT_sRGBFactors = MSFT_sRGBFactors;
+            GLTF2.GLTFLoader._Register(NAME, function (loader) { return new MSFT_sRGBFactors(loader); });
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=MSFT_sRGBFactors.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 NAME = "KHR_draco_mesh_compression";
             /**
              * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression)
@@ -2519,7 +2659,7 @@ var BABYLON;
                         if (!babylonData) {
                             var promises = new Array();
                             var name_1 = material.name || "materialSG_" + material._index;
-                            var babylonMaterial = _this._loader._createMaterial(BABYLON.PBRMaterial, name_1, babylonDrawMode);
+                            var babylonMaterial = _this._loader._createMaterial(name_1, babylonDrawMode);
                             promises.push(_this._loader._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                             promises.push(_this._loadSpecularGlossinessPropertiesAsync(extensionContext, material, extension, babylonMaterial));
                             _this._loader.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
@@ -2606,7 +2746,7 @@ var BABYLON;
                         var babylonData = material._babylonData[babylonDrawMode];
                         if (!babylonData) {
                             var name_1 = material.name || "materialUnlit_" + material._index;
-                            var babylonMaterial = _this._loader._createMaterial(BABYLON.PBRMaterial, name_1, babylonDrawMode);
+                            var babylonMaterial = _this._loader._createMaterial(name_1, babylonDrawMode);
                             babylonMaterial.unlit = true;
                             var promise = _this._loadUnlitPropertiesAsync(context, material, babylonMaterial);
                             _this._loader.onMaterialLoadedObservable.notifyObservers(babylonMaterial);

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 2 - 2
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


+ 63 - 19
dist/preview release/loaders/babylon.glTFFileLoader.d.ts

@@ -98,6 +98,16 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -199,6 +209,16 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -743,16 +763,15 @@ declare module BABYLON.GLTF1 {
         compileMaterials: boolean;
         useClipPlane: boolean;
         compileShadowGenerators: boolean;
-        onDisposeObservable: Observable<IGLTFLoader>;
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-        onTextureLoadedObservable: Observable<BaseTexture>;
-        onMaterialLoadedObservable: Observable<Material>;
-        onCameraLoadedObservable: Observable<Camera>;
-        onCompleteObservable: Observable<IGLTFLoader>;
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
-        * State of the loader
-        */
+        transparencyAsCoverage: boolean;
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
+        readonly onTextureLoadedObservable: Observable<BaseTexture>;
+        readonly onMaterialLoadedObservable: Observable<Material>;
+        readonly onCameraLoadedObservable: Observable<Camera>;
+        readonly onCompleteObservable: Observable<IGLTFLoader>;
+        readonly onDisposeObservable: Observable<IGLTFLoader>;
+        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         state: Nullable<GLTFLoaderState>;
         dispose(): void;
         private _importMeshAsync(meshesNames, scene, data, rootUrl, onSuccess, onProgress?, onError?);
@@ -1048,11 +1067,6 @@ declare module BABYLON.GLTF2 {
  * Defines the module used to import/export glTF 2.0 assets
  */
 declare module BABYLON.GLTF2 {
-    /** @hidden */
-    interface _MaterialConstructor<T extends Material> {
-        readonly prototype: T;
-        new (name: string, scene: Scene): T;
-    }
     /**
      * Loader for loading a glTF 2.0 asset
      */
@@ -1072,8 +1086,8 @@ declare module BABYLON.GLTF2 {
         private _defaultBabylonMaterials;
         private _progressCallback?;
         private _requests;
-        private static _Names;
-        private static _Factories;
+        private static _ExtensionNames;
+        private static _ExtensionFactories;
         /** @hidden */
         static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void;
         /**
@@ -1097,6 +1111,16 @@ declare module BABYLON.GLTF2 {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -1160,9 +1184,9 @@ declare module BABYLON.GLTF2 {
          */
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
         private _loadAsync(nodes, scene, data, rootUrl, onProgress?);
-        private _loadExtensions();
         private _loadData(data);
         private _setupData();
+        private _loadExtensions();
         private _checkExtensions();
         private _createRootNode();
         private _loadNodesAsync(nodes);
@@ -1206,7 +1230,7 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void>;
         /** @hidden */
-        _createMaterial<T extends Material>(type: _MaterialConstructor<T>, name: string, drawMode: number): T;
+        _createMaterial(name: string, drawMode: number): PBRMaterial;
         /** @hidden */
         _loadMaterialBasePropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void>;
         /** @hidden */
@@ -1302,6 +1326,26 @@ declare module BABYLON.GLTF2.Extensions {
 
 
 declare module BABYLON.GLTF2.Extensions {
+    /** @hidden */
+    class MSFT_minecraftMesh extends GLTFLoaderExtension {
+        readonly name: string;
+        constructor(loader: GLTFLoader);
+        private _onMaterialLoaded;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    /** @hidden */
+    class MSFT_sRGBFactors extends GLTFLoaderExtension {
+        readonly name: string;
+        constructor(loader: GLTFLoader);
+        private _onMaterialLoaded;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
     /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression)
      */

+ 189 - 54
dist/preview release/loaders/babylon.glTFFileLoader.js

@@ -84,6 +84,16 @@ var BABYLON;
              */
             this.compileShadowGenerators = false;
             /**
+             * Defines if the Alpha blended materials are only applied as coverage.
+             * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+             * If true, no extra effects are applied to transparent pixels.
+             */
+            this.transparencyAsCoverage = false;
+            /**
+             * Function called before loading a url referenced by the asset.
+             */
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+            /**
              * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
              */
             this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -262,6 +272,7 @@ var BABYLON;
                 this._loader.dispose();
                 this._loader = null;
             }
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
@@ -389,6 +400,8 @@ var BABYLON;
             loader.compileMaterials = this.compileMaterials;
             loader.useClipPlane = this.useClipPlane;
             loader.compileShadowGenerators = this.compileShadowGenerators;
+            loader.transparencyAsCoverage = this.transparencyAsCoverage;
+            loader.preprocessUrlAsync = this.preprocessUrlAsync;
             loader.onMeshLoadedObservable.add(function (mesh) { return _this.onMeshLoadedObservable.notifyObservers(mesh); });
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
@@ -1968,16 +1981,15 @@ var BABYLON;
                 this.compileMaterials = false;
                 this.useClipPlane = false;
                 this.compileShadowGenerators = false;
-                this.onDisposeObservable = new BABYLON.Observable();
+                this.transparencyAsCoverage = false;
+                this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
                 this.onMeshLoadedObservable = new BABYLON.Observable();
                 this.onTextureLoadedObservable = new BABYLON.Observable();
                 this.onMaterialLoadedObservable = new BABYLON.Observable();
                 this.onCameraLoadedObservable = new BABYLON.Observable();
                 this.onCompleteObservable = new BABYLON.Observable();
+                this.onDisposeObservable = new BABYLON.Observable();
                 this.onExtensionLoadedObservable = new BABYLON.Observable();
-                /**
-                * State of the loader
-                */
                 this.state = null;
             }
             GLTFLoader.RegisterExtension = function (extension) {
@@ -2864,6 +2876,16 @@ var BABYLON;
                  */
                 this.compileShadowGenerators = false;
                 /**
+                 * Defines if the Alpha blended materials are only applied as coverage.
+                 * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+                 * If true, no extra effects are applied to transparent pixels.
+                 */
+                this.transparencyAsCoverage = false;
+                /**
+                 * Function called before loading a url referenced by the asset.
+                 */
+                this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+                /**
                  * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
                  */
                 this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -2897,13 +2919,13 @@ var BABYLON;
             }
             /** @hidden */
             GLTFLoader._Register = function (name, factory) {
-                if (GLTFLoader._Factories[name]) {
+                if (GLTFLoader._ExtensionFactories[name]) {
                     BABYLON.Tools.Error("Extension with the name '" + name + "' already exists");
                     return;
                 }
-                GLTFLoader._Factories[name] = factory;
+                GLTFLoader._ExtensionFactories[name] = factory;
                 // Keep the order of registration so that extensions registered first are called first.
-                GLTFLoader._Names.push(name);
+                GLTFLoader._ExtensionNames.push(name);
             };
             Object.defineProperty(GLTFLoader.prototype, "state", {
                 /**
@@ -2983,12 +3005,12 @@ var BABYLON;
             GLTFLoader.prototype._loadAsync = function (nodes, scene, data, rootUrl, onProgress) {
                 var _this = this;
                 return Promise.resolve().then(function () {
-                    _this._loadExtensions();
                     _this._babylonScene = scene;
                     _this._rootUrl = rootUrl;
                     _this._progressCallback = onProgress;
                     _this._state = BABYLON.GLTFLoaderState.LOADING;
                     _this._loadData(data);
+                    _this._loadExtensions();
                     _this._checkExtensions();
                     var promises = new Array();
                     if (nodes) {
@@ -3026,20 +3048,13 @@ var BABYLON;
                     });
                     return resultPromise;
                 }).catch(function (error) {
-                    BABYLON.Tools.Error("glTF Loader: " + error.message);
-                    _this._clear();
-                    throw error;
+                    if (!_this._disposed) {
+                        BABYLON.Tools.Error("glTF Loader: " + error.message);
+                        _this._clear();
+                        throw error;
+                    }
                 });
             };
-            GLTFLoader.prototype._loadExtensions = function () {
-                for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
-                    var name_1 = _a[_i];
-                    var extension = GLTFLoader._Factories[name_1](this);
-                    this._extensions[name_1] = extension;
-                    this.onExtensionLoadedObservable.notifyObservers(extension);
-                }
-                this.onExtensionLoadedObservable.clear();
-            };
             GLTFLoader.prototype._loadData = function (data) {
                 this._gltf = data.json;
                 this._setupData();
@@ -3090,6 +3105,15 @@ var BABYLON;
                     }
                 }
             };
+            GLTFLoader.prototype._loadExtensions = function () {
+                for (var _i = 0, _a = GLTFLoader._ExtensionNames; _i < _a.length; _i++) {
+                    var name_1 = _a[_i];
+                    var extension = GLTFLoader._ExtensionFactories[name_1](this);
+                    this._extensions[name_1] = extension;
+                    this.onExtensionLoadedObservable.notifyObservers(extension);
+                }
+                this.onExtensionLoadedObservable.clear();
+            };
             GLTFLoader.prototype._checkExtensions = function () {
                 if (this._gltf.extensionsRequired) {
                     for (var _i = 0, _a = this._gltf.extensionsRequired; _i < _a.length; _i++) {
@@ -3903,7 +3927,7 @@ var BABYLON;
             GLTFLoader.prototype._getDefaultMaterial = function (drawMode) {
                 var babylonMaterial = this._defaultBabylonMaterials[drawMode];
                 if (!babylonMaterial) {
-                    babylonMaterial = this._createMaterial(BABYLON.PBRMaterial, "__gltf_default", drawMode);
+                    babylonMaterial = this._createMaterial("__gltf_default", drawMode);
                     babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE;
                     babylonMaterial.metallic = 1;
                     babylonMaterial.roughness = 1;
@@ -3955,7 +3979,7 @@ var BABYLON;
                 if (!babylonData) {
                     var promises = new Array();
                     var name_3 = material.name || "materialSG_" + material._index;
-                    var babylonMaterial = this._createMaterial(BABYLON.PBRMaterial, name_3, babylonDrawMode);
+                    var babylonMaterial = this._createMaterial(name_3, babylonDrawMode);
                     promises.push(this._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                     promises.push(this._loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial));
                     this.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
@@ -3971,10 +3995,13 @@ var BABYLON;
                 return babylonData.loaded;
             };
             /** @hidden */
-            GLTFLoader.prototype._createMaterial = function (type, name, drawMode) {
-                var babylonMaterial = new type(name, this._babylonScene);
+            GLTFLoader.prototype._createMaterial = function (name, drawMode) {
+                var babylonMaterial = new BABYLON.PBRMaterial(name, this._babylonScene);
                 babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? BABYLON.Material.CounterClockWiseSideOrientation : BABYLON.Material.ClockWiseSideOrientation;
                 babylonMaterial.fillMode = drawMode;
+                babylonMaterial.enableSpecularAntiAliasing = true;
+                babylonMaterial.useRadianceOverAlpha = !this.transparencyAsCoverage;
+                babylonMaterial.useSpecularOverAlpha = !this.transparencyAsCoverage;
                 return babylonMaterial;
             };
             /** @hidden */
@@ -4113,31 +4140,35 @@ var BABYLON;
                 if (BABYLON.Tools.IsBase64(uri)) {
                     return Promise.resolve(new Uint8Array(BABYLON.Tools.DecodeBase64(uri)));
                 }
-                return new Promise(function (resolve, reject) {
-                    var request = BABYLON.Tools.LoadFile(_this._rootUrl + uri, function (data) {
-                        if (!_this._disposed) {
-                            resolve(new Uint8Array(data));
-                        }
-                    }, function (event) {
+                return this.preprocessUrlAsync(this._rootUrl + uri).then(function (url) {
+                    return new Promise(function (resolve, reject) {
                         if (!_this._disposed) {
-                            try {
-                                if (request && _this._state === BABYLON.GLTFLoaderState.LOADING) {
-                                    request._lengthComputable = event.lengthComputable;
-                                    request._loaded = event.loaded;
-                                    request._total = event.total;
-                                    _this._onProgress();
+                            var request_1 = BABYLON.Tools.LoadFile(url, function (data) {
+                                if (!_this._disposed) {
+                                    resolve(new Uint8Array(data));
                                 }
-                            }
-                            catch (e) {
-                                reject(e);
-                            }
-                        }
-                    }, _this._babylonScene.database, true, function (request, exception) {
-                        if (!_this._disposed) {
-                            reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
+                            }, function (event) {
+                                if (!_this._disposed) {
+                                    try {
+                                        if (request_1 && _this._state === BABYLON.GLTFLoaderState.LOADING) {
+                                            request_1._lengthComputable = event.lengthComputable;
+                                            request_1._loaded = event.loaded;
+                                            request_1._total = event.total;
+                                            _this._onProgress();
+                                        }
+                                    }
+                                    catch (e) {
+                                        reject(e);
+                                    }
+                                }
+                            }, _this._babylonScene.database, true, function (request, exception) {
+                                if (!_this._disposed) {
+                                    reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
+                                }
+                            });
+                            _this._requests.push(request_1);
                         }
                     });
-                    _this._requests.push(request);
                 });
             };
             GLTFLoader.prototype._onProgress = function () {
@@ -4328,7 +4359,7 @@ var BABYLON;
             };
             /** @hidden */
             GLTFLoader.prototype._applyExtensions = function (actionAsync) {
-                for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
+                for (var _i = 0, _a = GLTFLoader._ExtensionNames; _i < _a.length; _i++) {
                     var name_5 = _a[_i];
                     var extension = this._extensions[name_5];
                     if (extension.enabled) {
@@ -4340,8 +4371,8 @@ var BABYLON;
                 }
                 return null;
             };
-            GLTFLoader._Names = new Array();
-            GLTFLoader._Factories = {};
+            GLTFLoader._ExtensionNames = new Array();
+            GLTFLoader._ExtensionFactories = {};
             return GLTFLoader;
         }());
         GLTF2.GLTFLoader = GLTFLoader;
@@ -4616,6 +4647,114 @@ var BABYLON;
     (function (GLTF2) {
         var Extensions;
         (function (Extensions) {
+            var NAME = "MSFT_minecraftMesh";
+            /** @hidden */
+            var MSFT_minecraftMesh = /** @class */ (function (_super) {
+                __extends(MSFT_minecraftMesh, _super);
+                function MSFT_minecraftMesh(loader) {
+                    var _this = _super.call(this, loader) || this;
+                    _this.name = NAME;
+                    _this._onMaterialLoaded = function (material) {
+                        if (material.needAlphaBlending()) {
+                            material.forceDepthWrite = true;
+                            material.separateCullingPass = true;
+                        }
+                        material.backFaceCulling = material.forceDepthWrite;
+                        material.twoSidedLighting = true;
+                    };
+                    var meshes = loader._gltf.meshes;
+                    if (meshes && meshes.length) {
+                        for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                            var mesh = meshes_1[_i];
+                            if (mesh && mesh.extras && mesh.extras.MSFT_minecraftMesh) {
+                                _this._loader.onMaterialLoadedObservable.add(_this._onMaterialLoaded);
+                                break;
+                            }
+                        }
+                    }
+                    return _this;
+                }
+                return MSFT_minecraftMesh;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.MSFT_minecraftMesh = MSFT_minecraftMesh;
+            GLTF2.GLTFLoader._Register(NAME, function (loader) { return new MSFT_minecraftMesh(loader); });
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=MSFT_minecraftMesh.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 NAME = "MSFT_sRGBFactors";
+            /** @hidden */
+            var MSFT_sRGBFactors = /** @class */ (function (_super) {
+                __extends(MSFT_sRGBFactors, _super);
+                function MSFT_sRGBFactors(loader) {
+                    var _this = _super.call(this, loader) || this;
+                    _this.name = NAME;
+                    _this._onMaterialLoaded = function (material) {
+                        if (!material.albedoTexture) {
+                            material.albedoColor.toLinearSpaceToRef(material.albedoColor);
+                        }
+                        if (!material.reflectivityTexture) {
+                            material.reflectivityColor.toLinearSpaceToRef(material.reflectivityColor);
+                        }
+                    };
+                    var materials = loader._gltf.materials;
+                    if (materials && materials.length) {
+                        for (var _i = 0, materials_1 = materials; _i < materials_1.length; _i++) {
+                            var material = materials_1[_i];
+                            if (material && material.extras && material.extras.MSFT_sRGBFactors) {
+                                _this._loader.onMaterialLoadedObservable.add(_this._onMaterialLoaded);
+                                break;
+                            }
+                        }
+                    }
+                    return _this;
+                }
+                return MSFT_sRGBFactors;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.MSFT_sRGBFactors = MSFT_sRGBFactors;
+            GLTF2.GLTFLoader._Register(NAME, function (loader) { return new MSFT_sRGBFactors(loader); });
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=MSFT_sRGBFactors.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 NAME = "KHR_draco_mesh_compression";
             /**
              * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression)
@@ -4735,7 +4874,7 @@ var BABYLON;
                         if (!babylonData) {
                             var promises = new Array();
                             var name_1 = material.name || "materialSG_" + material._index;
-                            var babylonMaterial = _this._loader._createMaterial(BABYLON.PBRMaterial, name_1, babylonDrawMode);
+                            var babylonMaterial = _this._loader._createMaterial(name_1, babylonDrawMode);
                             promises.push(_this._loader._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                             promises.push(_this._loadSpecularGlossinessPropertiesAsync(extensionContext, material, extension, babylonMaterial));
                             _this._loader.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
@@ -4822,7 +4961,7 @@ var BABYLON;
                         var babylonData = material._babylonData[babylonDrawMode];
                         if (!babylonData) {
                             var name_1 = material.name || "materialUnlit_" + material._index;
-                            var babylonMaterial = _this._loader._createMaterial(BABYLON.PBRMaterial, name_1, babylonDrawMode);
+                            var babylonMaterial = _this._loader._createMaterial(name_1, babylonDrawMode);
                             babylonMaterial.unlit = true;
                             var promise = _this._loadUnlitPropertiesAsync(context, material, babylonMaterial);
                             _this._loader.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
@@ -4873,8 +5012,6 @@ var BABYLON;
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
-//# sourceMappingURL=KHR_materials_unlit.js.map
-
 /// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
 var __extends = (this && this.__extends) || (function () {
     var extendStatics = Object.setPrototypeOf ||
@@ -4978,5 +5115,3 @@ var BABYLON;
         })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
-
-//# sourceMappingURL=KHR_lights.js.map

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 3 - 3
dist/preview release/loaders/babylon.glTFFileLoader.min.js


+ 63 - 19
dist/preview release/loaders/babylonjs.loaders.d.ts

@@ -194,6 +194,16 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -295,6 +305,16 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -839,16 +859,15 @@ declare module BABYLON.GLTF1 {
         compileMaterials: boolean;
         useClipPlane: boolean;
         compileShadowGenerators: boolean;
-        onDisposeObservable: Observable<IGLTFLoader>;
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-        onTextureLoadedObservable: Observable<BaseTexture>;
-        onMaterialLoadedObservable: Observable<Material>;
-        onCameraLoadedObservable: Observable<Camera>;
-        onCompleteObservable: Observable<IGLTFLoader>;
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
-        * State of the loader
-        */
+        transparencyAsCoverage: boolean;
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
+        readonly onTextureLoadedObservable: Observable<BaseTexture>;
+        readonly onMaterialLoadedObservable: Observable<Material>;
+        readonly onCameraLoadedObservable: Observable<Camera>;
+        readonly onCompleteObservable: Observable<IGLTFLoader>;
+        readonly onDisposeObservable: Observable<IGLTFLoader>;
+        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         state: Nullable<GLTFLoaderState>;
         dispose(): void;
         private _importMeshAsync(meshesNames, scene, data, rootUrl, onSuccess, onProgress?, onError?);
@@ -1144,11 +1163,6 @@ declare module BABYLON.GLTF2 {
  * Defines the module used to import/export glTF 2.0 assets
  */
 declare module BABYLON.GLTF2 {
-    /** @hidden */
-    interface _MaterialConstructor<T extends Material> {
-        readonly prototype: T;
-        new (name: string, scene: Scene): T;
-    }
     /**
      * Loader for loading a glTF 2.0 asset
      */
@@ -1168,8 +1182,8 @@ declare module BABYLON.GLTF2 {
         private _defaultBabylonMaterials;
         private _progressCallback?;
         private _requests;
-        private static _Names;
-        private static _Factories;
+        private static _ExtensionNames;
+        private static _ExtensionFactories;
         /** @hidden */
         static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void;
         /**
@@ -1193,6 +1207,16 @@ declare module BABYLON.GLTF2 {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -1256,9 +1280,9 @@ declare module BABYLON.GLTF2 {
          */
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
         private _loadAsync(nodes, scene, data, rootUrl, onProgress?);
-        private _loadExtensions();
         private _loadData(data);
         private _setupData();
+        private _loadExtensions();
         private _checkExtensions();
         private _createRootNode();
         private _loadNodesAsync(nodes);
@@ -1302,7 +1326,7 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void>;
         /** @hidden */
-        _createMaterial<T extends Material>(type: _MaterialConstructor<T>, name: string, drawMode: number): T;
+        _createMaterial(name: string, drawMode: number): PBRMaterial;
         /** @hidden */
         _loadMaterialBasePropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void>;
         /** @hidden */
@@ -1398,6 +1422,26 @@ declare module BABYLON.GLTF2.Extensions {
 
 
 declare module BABYLON.GLTF2.Extensions {
+    /** @hidden */
+    class MSFT_minecraftMesh extends GLTFLoaderExtension {
+        readonly name: string;
+        constructor(loader: GLTFLoader);
+        private _onMaterialLoaded;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    /** @hidden */
+    class MSFT_sRGBFactors extends GLTFLoaderExtension {
+        readonly name: string;
+        constructor(loader: GLTFLoader);
+        private _onMaterialLoaded;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
     /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression)
      */

+ 171 - 54
dist/preview release/loaders/babylonjs.loaders.js

@@ -1084,6 +1084,16 @@ var BABYLON;
              */
             this.compileShadowGenerators = false;
             /**
+             * Defines if the Alpha blended materials are only applied as coverage.
+             * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+             * If true, no extra effects are applied to transparent pixels.
+             */
+            this.transparencyAsCoverage = false;
+            /**
+             * Function called before loading a url referenced by the asset.
+             */
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+            /**
              * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
              */
             this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -1262,6 +1272,7 @@ var BABYLON;
                 this._loader.dispose();
                 this._loader = null;
             }
+            this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
@@ -1389,6 +1400,8 @@ var BABYLON;
             loader.compileMaterials = this.compileMaterials;
             loader.useClipPlane = this.useClipPlane;
             loader.compileShadowGenerators = this.compileShadowGenerators;
+            loader.transparencyAsCoverage = this.transparencyAsCoverage;
+            loader.preprocessUrlAsync = this.preprocessUrlAsync;
             loader.onMeshLoadedObservable.add(function (mesh) { return _this.onMeshLoadedObservable.notifyObservers(mesh); });
             loader.onTextureLoadedObservable.add(function (texture) { return _this.onTextureLoadedObservable.notifyObservers(texture); });
             loader.onMaterialLoadedObservable.add(function (material) { return _this.onMaterialLoadedObservable.notifyObservers(material); });
@@ -2968,16 +2981,15 @@ var BABYLON;
                 this.compileMaterials = false;
                 this.useClipPlane = false;
                 this.compileShadowGenerators = false;
-                this.onDisposeObservable = new BABYLON.Observable();
+                this.transparencyAsCoverage = false;
+                this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
                 this.onMeshLoadedObservable = new BABYLON.Observable();
                 this.onTextureLoadedObservable = new BABYLON.Observable();
                 this.onMaterialLoadedObservable = new BABYLON.Observable();
                 this.onCameraLoadedObservable = new BABYLON.Observable();
                 this.onCompleteObservable = new BABYLON.Observable();
+                this.onDisposeObservable = new BABYLON.Observable();
                 this.onExtensionLoadedObservable = new BABYLON.Observable();
-                /**
-                * State of the loader
-                */
                 this.state = null;
             }
             GLTFLoader.RegisterExtension = function (extension) {
@@ -3846,6 +3858,16 @@ var BABYLON;
                  */
                 this.compileShadowGenerators = false;
                 /**
+                 * Defines if the Alpha blended materials are only applied as coverage.
+                 * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+                 * If true, no extra effects are applied to transparent pixels.
+                 */
+                this.transparencyAsCoverage = false;
+                /**
+                 * Function called before loading a url referenced by the asset.
+                 */
+                this.preprocessUrlAsync = function (url) { return Promise.resolve(url); };
+                /**
                  * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
                  */
                 this.onMeshLoadedObservable = new BABYLON.Observable();
@@ -3879,13 +3901,13 @@ var BABYLON;
             }
             /** @hidden */
             GLTFLoader._Register = function (name, factory) {
-                if (GLTFLoader._Factories[name]) {
+                if (GLTFLoader._ExtensionFactories[name]) {
                     BABYLON.Tools.Error("Extension with the name '" + name + "' already exists");
                     return;
                 }
-                GLTFLoader._Factories[name] = factory;
+                GLTFLoader._ExtensionFactories[name] = factory;
                 // Keep the order of registration so that extensions registered first are called first.
-                GLTFLoader._Names.push(name);
+                GLTFLoader._ExtensionNames.push(name);
             };
             Object.defineProperty(GLTFLoader.prototype, "state", {
                 /**
@@ -3965,12 +3987,12 @@ var BABYLON;
             GLTFLoader.prototype._loadAsync = function (nodes, scene, data, rootUrl, onProgress) {
                 var _this = this;
                 return Promise.resolve().then(function () {
-                    _this._loadExtensions();
                     _this._babylonScene = scene;
                     _this._rootUrl = rootUrl;
                     _this._progressCallback = onProgress;
                     _this._state = BABYLON.GLTFLoaderState.LOADING;
                     _this._loadData(data);
+                    _this._loadExtensions();
                     _this._checkExtensions();
                     var promises = new Array();
                     if (nodes) {
@@ -4008,20 +4030,13 @@ var BABYLON;
                     });
                     return resultPromise;
                 }).catch(function (error) {
-                    BABYLON.Tools.Error("glTF Loader: " + error.message);
-                    _this._clear();
-                    throw error;
+                    if (!_this._disposed) {
+                        BABYLON.Tools.Error("glTF Loader: " + error.message);
+                        _this._clear();
+                        throw error;
+                    }
                 });
             };
-            GLTFLoader.prototype._loadExtensions = function () {
-                for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
-                    var name_1 = _a[_i];
-                    var extension = GLTFLoader._Factories[name_1](this);
-                    this._extensions[name_1] = extension;
-                    this.onExtensionLoadedObservable.notifyObservers(extension);
-                }
-                this.onExtensionLoadedObservable.clear();
-            };
             GLTFLoader.prototype._loadData = function (data) {
                 this._gltf = data.json;
                 this._setupData();
@@ -4072,6 +4087,15 @@ var BABYLON;
                     }
                 }
             };
+            GLTFLoader.prototype._loadExtensions = function () {
+                for (var _i = 0, _a = GLTFLoader._ExtensionNames; _i < _a.length; _i++) {
+                    var name_1 = _a[_i];
+                    var extension = GLTFLoader._ExtensionFactories[name_1](this);
+                    this._extensions[name_1] = extension;
+                    this.onExtensionLoadedObservable.notifyObservers(extension);
+                }
+                this.onExtensionLoadedObservable.clear();
+            };
             GLTFLoader.prototype._checkExtensions = function () {
                 if (this._gltf.extensionsRequired) {
                     for (var _i = 0, _a = this._gltf.extensionsRequired; _i < _a.length; _i++) {
@@ -4885,7 +4909,7 @@ var BABYLON;
             GLTFLoader.prototype._getDefaultMaterial = function (drawMode) {
                 var babylonMaterial = this._defaultBabylonMaterials[drawMode];
                 if (!babylonMaterial) {
-                    babylonMaterial = this._createMaterial(BABYLON.PBRMaterial, "__gltf_default", drawMode);
+                    babylonMaterial = this._createMaterial("__gltf_default", drawMode);
                     babylonMaterial.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_OPAQUE;
                     babylonMaterial.metallic = 1;
                     babylonMaterial.roughness = 1;
@@ -4937,7 +4961,7 @@ var BABYLON;
                 if (!babylonData) {
                     var promises = new Array();
                     var name_3 = material.name || "materialSG_" + material._index;
-                    var babylonMaterial = this._createMaterial(BABYLON.PBRMaterial, name_3, babylonDrawMode);
+                    var babylonMaterial = this._createMaterial(name_3, babylonDrawMode);
                     promises.push(this._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                     promises.push(this._loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial));
                     this.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
@@ -4953,10 +4977,13 @@ var BABYLON;
                 return babylonData.loaded;
             };
             /** @hidden */
-            GLTFLoader.prototype._createMaterial = function (type, name, drawMode) {
-                var babylonMaterial = new type(name, this._babylonScene);
+            GLTFLoader.prototype._createMaterial = function (name, drawMode) {
+                var babylonMaterial = new BABYLON.PBRMaterial(name, this._babylonScene);
                 babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? BABYLON.Material.CounterClockWiseSideOrientation : BABYLON.Material.ClockWiseSideOrientation;
                 babylonMaterial.fillMode = drawMode;
+                babylonMaterial.enableSpecularAntiAliasing = true;
+                babylonMaterial.useRadianceOverAlpha = !this.transparencyAsCoverage;
+                babylonMaterial.useSpecularOverAlpha = !this.transparencyAsCoverage;
                 return babylonMaterial;
             };
             /** @hidden */
@@ -5095,31 +5122,35 @@ var BABYLON;
                 if (BABYLON.Tools.IsBase64(uri)) {
                     return Promise.resolve(new Uint8Array(BABYLON.Tools.DecodeBase64(uri)));
                 }
-                return new Promise(function (resolve, reject) {
-                    var request = BABYLON.Tools.LoadFile(_this._rootUrl + uri, function (data) {
-                        if (!_this._disposed) {
-                            resolve(new Uint8Array(data));
-                        }
-                    }, function (event) {
+                return this.preprocessUrlAsync(this._rootUrl + uri).then(function (url) {
+                    return new Promise(function (resolve, reject) {
                         if (!_this._disposed) {
-                            try {
-                                if (request && _this._state === BABYLON.GLTFLoaderState.LOADING) {
-                                    request._lengthComputable = event.lengthComputable;
-                                    request._loaded = event.loaded;
-                                    request._total = event.total;
-                                    _this._onProgress();
+                            var request_1 = BABYLON.Tools.LoadFile(url, function (data) {
+                                if (!_this._disposed) {
+                                    resolve(new Uint8Array(data));
                                 }
-                            }
-                            catch (e) {
-                                reject(e);
-                            }
-                        }
-                    }, _this._babylonScene.database, true, function (request, exception) {
-                        if (!_this._disposed) {
-                            reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
+                            }, function (event) {
+                                if (!_this._disposed) {
+                                    try {
+                                        if (request_1 && _this._state === BABYLON.GLTFLoaderState.LOADING) {
+                                            request_1._lengthComputable = event.lengthComputable;
+                                            request_1._loaded = event.loaded;
+                                            request_1._total = event.total;
+                                            _this._onProgress();
+                                        }
+                                    }
+                                    catch (e) {
+                                        reject(e);
+                                    }
+                                }
+                            }, _this._babylonScene.database, true, function (request, exception) {
+                                if (!_this._disposed) {
+                                    reject(new BABYLON.LoadFileError(context + ": Failed to load '" + uri + "'" + (request ? ": " + request.status + " " + request.statusText : ""), request));
+                                }
+                            });
+                            _this._requests.push(request_1);
                         }
                     });
-                    _this._requests.push(request);
                 });
             };
             GLTFLoader.prototype._onProgress = function () {
@@ -5310,7 +5341,7 @@ var BABYLON;
             };
             /** @hidden */
             GLTFLoader.prototype._applyExtensions = function (actionAsync) {
-                for (var _i = 0, _a = GLTFLoader._Names; _i < _a.length; _i++) {
+                for (var _i = 0, _a = GLTFLoader._ExtensionNames; _i < _a.length; _i++) {
                     var name_5 = _a[_i];
                     var extension = this._extensions[name_5];
                     if (extension.enabled) {
@@ -5322,8 +5353,8 @@ var BABYLON;
                 }
                 return null;
             };
-            GLTFLoader._Names = new Array();
-            GLTFLoader._Factories = {};
+            GLTFLoader._ExtensionNames = new Array();
+            GLTFLoader._ExtensionFactories = {};
             return GLTFLoader;
         }());
         GLTF2.GLTFLoader = GLTFLoader;
@@ -5580,6 +5611,96 @@ var BABYLON;
     (function (GLTF2) {
         var Extensions;
         (function (Extensions) {
+            var NAME = "MSFT_minecraftMesh";
+            /** @hidden */
+            var MSFT_minecraftMesh = /** @class */ (function (_super) {
+                __extends(MSFT_minecraftMesh, _super);
+                function MSFT_minecraftMesh(loader) {
+                    var _this = _super.call(this, loader) || this;
+                    _this.name = NAME;
+                    _this._onMaterialLoaded = function (material) {
+                        if (material.needAlphaBlending()) {
+                            material.forceDepthWrite = true;
+                            material.separateCullingPass = true;
+                        }
+                        material.backFaceCulling = material.forceDepthWrite;
+                        material.twoSidedLighting = true;
+                    };
+                    var meshes = loader._gltf.meshes;
+                    if (meshes && meshes.length) {
+                        for (var _i = 0, meshes_1 = meshes; _i < meshes_1.length; _i++) {
+                            var mesh = meshes_1[_i];
+                            if (mesh && mesh.extras && mesh.extras.MSFT_minecraftMesh) {
+                                _this._loader.onMaterialLoadedObservable.add(_this._onMaterialLoaded);
+                                break;
+                            }
+                        }
+                    }
+                    return _this;
+                }
+                return MSFT_minecraftMesh;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.MSFT_minecraftMesh = MSFT_minecraftMesh;
+            GLTF2.GLTFLoader._Register(NAME, function (loader) { return new MSFT_minecraftMesh(loader); });
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=MSFT_minecraftMesh.js.map
+
+
+
+var BABYLON;
+(function (BABYLON) {
+    var GLTF2;
+    (function (GLTF2) {
+        var Extensions;
+        (function (Extensions) {
+            var NAME = "MSFT_sRGBFactors";
+            /** @hidden */
+            var MSFT_sRGBFactors = /** @class */ (function (_super) {
+                __extends(MSFT_sRGBFactors, _super);
+                function MSFT_sRGBFactors(loader) {
+                    var _this = _super.call(this, loader) || this;
+                    _this.name = NAME;
+                    _this._onMaterialLoaded = function (material) {
+                        if (!material.albedoTexture) {
+                            material.albedoColor.toLinearSpaceToRef(material.albedoColor);
+                        }
+                        if (!material.reflectivityTexture) {
+                            material.reflectivityColor.toLinearSpaceToRef(material.reflectivityColor);
+                        }
+                    };
+                    var materials = loader._gltf.materials;
+                    if (materials && materials.length) {
+                        for (var _i = 0, materials_1 = materials; _i < materials_1.length; _i++) {
+                            var material = materials_1[_i];
+                            if (material && material.extras && material.extras.MSFT_sRGBFactors) {
+                                _this._loader.onMaterialLoadedObservable.add(_this._onMaterialLoaded);
+                                break;
+                            }
+                        }
+                    }
+                    return _this;
+                }
+                return MSFT_sRGBFactors;
+            }(GLTF2.GLTFLoaderExtension));
+            Extensions.MSFT_sRGBFactors = MSFT_sRGBFactors;
+            GLTF2.GLTFLoader._Register(NAME, function (loader) { return new MSFT_sRGBFactors(loader); });
+        })(Extensions = GLTF2.Extensions || (GLTF2.Extensions = {}));
+    })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
+})(BABYLON || (BABYLON = {}));
+
+//# sourceMappingURL=MSFT_sRGBFactors.js.map
+
+
+
+var BABYLON;
+(function (BABYLON) {
+    var GLTF2;
+    (function (GLTF2) {
+        var Extensions;
+        (function (Extensions) {
             var NAME = "KHR_draco_mesh_compression";
             /**
              * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression)
@@ -5690,7 +5811,7 @@ var BABYLON;
                         if (!babylonData) {
                             var promises = new Array();
                             var name_1 = material.name || "materialSG_" + material._index;
-                            var babylonMaterial = _this._loader._createMaterial(BABYLON.PBRMaterial, name_1, babylonDrawMode);
+                            var babylonMaterial = _this._loader._createMaterial(name_1, babylonDrawMode);
                             promises.push(_this._loader._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                             promises.push(_this._loadSpecularGlossinessPropertiesAsync(extensionContext, material, extension, babylonMaterial));
                             _this._loader.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
@@ -5768,7 +5889,7 @@ var BABYLON;
                         var babylonData = material._babylonData[babylonDrawMode];
                         if (!babylonData) {
                             var name_1 = material.name || "materialUnlit_" + material._index;
-                            var babylonMaterial = _this._loader._createMaterial(BABYLON.PBRMaterial, name_1, babylonDrawMode);
+                            var babylonMaterial = _this._loader._createMaterial(name_1, babylonDrawMode);
                             babylonMaterial.unlit = true;
                             var promise = _this._loadUnlitPropertiesAsync(context, material, babylonMaterial);
                             _this._loader.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
@@ -5819,8 +5940,6 @@ var BABYLON;
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
-//# sourceMappingURL=KHR_materials_unlit.js.map
-
 
 
 var BABYLON;
@@ -5916,8 +6035,6 @@ var BABYLON;
     })(GLTF2 = BABYLON.GLTF2 || (BABYLON.GLTF2 = {}));
 })(BABYLON || (BABYLON = {}));
 
-//# sourceMappingURL=KHR_lights.js.map
-
     
 
     return BABYLON;

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 4 - 4
dist/preview release/loaders/babylonjs.loaders.min.js


+ 63 - 19
dist/preview release/loaders/babylonjs.loaders.module.d.ts

@@ -201,6 +201,16 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -302,6 +312,16 @@ declare module BABYLON {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -846,16 +866,15 @@ declare module BABYLON.GLTF1 {
         compileMaterials: boolean;
         useClipPlane: boolean;
         compileShadowGenerators: boolean;
-        onDisposeObservable: Observable<IGLTFLoader>;
-        onMeshLoadedObservable: Observable<AbstractMesh>;
-        onTextureLoadedObservable: Observable<BaseTexture>;
-        onMaterialLoadedObservable: Observable<Material>;
-        onCameraLoadedObservable: Observable<Camera>;
-        onCompleteObservable: Observable<IGLTFLoader>;
-        onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
-        /**
-        * State of the loader
-        */
+        transparencyAsCoverage: boolean;
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        readonly onMeshLoadedObservable: Observable<AbstractMesh>;
+        readonly onTextureLoadedObservable: Observable<BaseTexture>;
+        readonly onMaterialLoadedObservable: Observable<Material>;
+        readonly onCameraLoadedObservable: Observable<Camera>;
+        readonly onCompleteObservable: Observable<IGLTFLoader>;
+        readonly onDisposeObservable: Observable<IGLTFLoader>;
+        readonly onExtensionLoadedObservable: Observable<IGLTFLoaderExtension>;
         state: Nullable<GLTFLoaderState>;
         dispose(): void;
         private _importMeshAsync(meshesNames, scene, data, rootUrl, onSuccess, onProgress?, onError?);
@@ -1151,11 +1170,6 @@ declare module BABYLON.GLTF2 {
  * Defines the module used to import/export glTF 2.0 assets
  */
 declare module BABYLON.GLTF2 {
-    /** @hidden */
-    interface _MaterialConstructor<T extends Material> {
-        readonly prototype: T;
-        new (name: string, scene: Scene): T;
-    }
     /**
      * Loader for loading a glTF 2.0 asset
      */
@@ -1175,8 +1189,8 @@ declare module BABYLON.GLTF2 {
         private _defaultBabylonMaterials;
         private _progressCallback?;
         private _requests;
-        private static _Names;
-        private static _Factories;
+        private static _ExtensionNames;
+        private static _ExtensionFactories;
         /** @hidden */
         static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void;
         /**
@@ -1200,6 +1214,16 @@ declare module BABYLON.GLTF2 {
          */
         compileShadowGenerators: boolean;
         /**
+         * Defines if the Alpha blended materials are only applied as coverage.
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         readonly onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -1263,9 +1287,9 @@ declare module BABYLON.GLTF2 {
          */
         loadAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void>;
         private _loadAsync(nodes, scene, data, rootUrl, onProgress?);
-        private _loadExtensions();
         private _loadData(data);
         private _setupData();
+        private _loadExtensions();
         private _checkExtensions();
         private _createRootNode();
         private _loadNodesAsync(nodes);
@@ -1309,7 +1333,7 @@ declare module BABYLON.GLTF2 {
         /** @hidden */
         _loadMaterialAsync(context: string, material: _ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Promise<void>;
         /** @hidden */
-        _createMaterial<T extends Material>(type: _MaterialConstructor<T>, name: string, drawMode: number): T;
+        _createMaterial(name: string, drawMode: number): PBRMaterial;
         /** @hidden */
         _loadMaterialBasePropertiesAsync(context: string, material: _ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void>;
         /** @hidden */
@@ -1405,6 +1429,26 @@ declare module BABYLON.GLTF2.Extensions {
 
 
 declare module BABYLON.GLTF2.Extensions {
+    /** @hidden */
+    class MSFT_minecraftMesh extends GLTFLoaderExtension {
+        readonly name: string;
+        constructor(loader: GLTFLoader);
+        private _onMaterialLoaded;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
+    /** @hidden */
+    class MSFT_sRGBFactors extends GLTFLoaderExtension {
+        readonly name: string;
+        constructor(loader: GLTFLoader);
+        private _onMaterialLoaded;
+    }
+}
+
+
+declare module BABYLON.GLTF2.Extensions {
     /**
      * [Specification](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression)
      */

+ 2 - 2
dist/preview release/loaders/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-loaders",
     "description": "The Babylon.js file loaders library is an extension you can use to load different 3D file types into a Babylon scene.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs-gltf2interface": "3.2.0-beta.5"
+        "babylonjs-gltf2interface": "3.2.0-rc.1"
     },
     "peerDependencies": {
         "babylonjs": ">=3.2.0-alpha"

+ 1 - 1
dist/preview release/materialsLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-materials",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 1 - 1
dist/preview release/postProcessesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-post-process",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 1 - 1
dist/preview release/proceduralTexturesLibrary/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-procedural-textures",
     "description": "The Babylon.js materials library is a collection of advanced materials to be used in a Babylon.js scene.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 2 - 2
dist/preview release/serializers/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-serializers",
     "description": "The Babylon.js serializers library is an extension you can use to serialize Babylon scenes.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"
@@ -27,7 +27,7 @@
     ],
     "license": "Apache-2.0",
     "dependencies": {
-        "babylonjs-gltf2interface": "3.2.0-beta.5"
+        "babylonjs-gltf2interface": "3.2.0-rc.1"
     },
     "peerDependencies": {
         "babylonjs": ">=3.2.0-alpha"

+ 2 - 136
dist/preview release/typedocValidationBaseline.json

@@ -1,7 +1,7 @@
 {
-  "errors": 4354,
+  "errors": 4330,
   "babylon.typedoc.json": {
-    "errors": 4354,
+    "errors": 4330,
     "Animatable": {
       "Class": {
         "Comments": {
@@ -4926,140 +4926,6 @@
         }
       }
     },
-    "Database": {
-      "Class": {
-        "Comments": {
-          "MissingText": true
-        }
-      },
-      "Constructor": {
-        "new Database": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "urlToScene": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "callbackManifestChecked": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        }
-      },
-      "Property": {
-        "enableSceneOffline": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "enableTexturesOffline": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "IDBStorageEnabled": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "IsUASupportingBlobStorage": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "ReturnFullUrlLocation": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "parseURL": {
-          "Naming": {
-            "NotPascalCase": true
-          },
-          "Comments": {
-            "MissingText": true
-          }
-        }
-      },
-      "Method": {
-        "checkManifestFile": {
-          "Comments": {
-            "MissingText": true
-          }
-        },
-        "loadFileFromDB": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "url": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "sceneLoaded": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "progressCallBack": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "errorCallback": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "useArrayBuffer": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "loadImageFromDB": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "url": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "image": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        },
-        "openAsync": {
-          "Comments": {
-            "MissingText": true
-          },
-          "Parameter": {
-            "successCallback": {
-              "Comments": {
-                "MissingText": true
-              }
-            },
-            "errorCallback": {
-              "Comments": {
-                "MissingText": true
-              }
-            }
-          }
-        }
-      }
-    },
     "DebugLayer": {
       "Class": {
         "Comments": {

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 32 - 32
dist/preview release/viewer/babylon.viewer.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 245 - 71
dist/preview release/viewer/babylon.viewer.max.js


+ 1 - 1
dist/preview release/viewer/package.json

@@ -4,7 +4,7 @@
     },
     "name": "babylonjs-viewer",
     "description": "A simple-to-use viewer based on BabylonJS to display 3D elements natively",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

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

@@ -21,7 +21,7 @@
 - New [glTF exporter](http://doc.babylonjs.com/resources/3dsmax_to_gltf) for Autodesk 3dsmax ([Noalak](https://github.com/Noalak))
 - Physics - Latest production version of Oimo.js is being used - 1.0.9 ([RaananW](https://github.com/RaananW))
 - Introduces [PCF](https://doc.babylonjs.com/babylon101/shadows#percentage-closer-filtering-webgl2-only) and [PCSS](https://doc.babylonjs.com/babylon101/shadows#contact-hardening-shadow-webgl2-only) shadow support in Webgl 2 ([sebavan](https://github.com/sebavan)))
-- Introduces PBR Specular Anti Aliasing support ([sebavan](https://github.com/sebavan)))
+- Introduces [PBR Specular Anti Aliasing support](https://doc.babylonjs.com/how_to/physically_based_rendering_master#specular-aliasing) ([sebavan](https://github.com/sebavan)))
 
 ## Documentation
 
@@ -118,6 +118,7 @@
 - Added alphaCutOff support for StandardMaterial ([deltakosh](https://github.com/deltakosh))
 - Add support for sparse accessors to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
 - Add support for cameras to glTF 2.0 loader. ([bghgary](https://github.com/bghgary)]
+- Add support for preprocessing urls to glTF 2.0 loader. ([bghgary](https://github.com/bghgary)]
 
 ## Bug fixes
 

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

@@ -107,6 +107,15 @@ module BABYLON.GUI {
        */
         public onAfterDrawObservable = new Observable<Control>();
 
+        /** Gets or set information about font offsets (used to render and align text) */
+        public get fontOffset(): { ascent: number, height: number, descent: number } {
+            return this._fontOffset;
+        }
+
+        public set fontOffset(offset: { ascent: number, height: number, descent: number }) {
+            this._fontOffset = offset;
+        }
+
         public get alpha(): number {
             return this._alpha;
         }

+ 1 - 0
inspector/sass/main.scss

@@ -93,6 +93,7 @@
   @import "tabs/shaderTab";
   @import "tabs/consoleTab";
   @import "tabs/statsTab";
+  @import "tabs/gltfTab";
 
   @import "tree";
   @import "detailPanel";

+ 45 - 0
inspector/sass/tabs/_gltfTab.scss

@@ -0,0 +1,45 @@
+.tab-panel {
+    .gltf-actions {
+        overflow-y: auto;
+        padding-left: 5px;
+
+        .gltf-title {
+            font-size     : 1.1em;
+            padding-bottom: 10px;
+            border-bottom : 1px solid $color-bot;
+            margin        : 10px 0 10px 0;
+        }
+
+        .gltf-input {
+            background-color: $background-lighter;
+            border          : none;
+            outline         : none;
+            font-family     : $font;
+            color           : darken($color, 10%);
+            padding         : 5px;
+            margin          : 0px 6px 0px 0;
+
+            &:hover {
+                background-color:$background-lighter2;
+            }
+        }
+
+        .gltf-button {
+            background-color: $background-lighter;
+            border          : none;
+            outline         : none;
+            font-family     : $font;
+            color           : $color;
+            padding         : 5px 10px;
+            margin          : 0px 6px 0px 0;
+
+            &:hover {
+                background-color:$background-lighter2;
+            }
+
+            &:active {
+                background-color:$background-lighter3;
+            }
+        }
+    }
+}

+ 53 - 0
inspector/src/tabs/GLTFTab.ts

@@ -0,0 +1,53 @@
+/// <reference path="../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts"/>
+
+module INSPECTOR {
+    export class GLTFTab extends Tab {
+        constructor(tabbar: TabBar, inspector: Inspector) {
+            super(tabbar, 'GLTF');
+
+            this._panel = Helpers.CreateDiv('tab-panel') as HTMLDivElement;
+            const actions = Helpers.CreateDiv('gltf-actions', this._panel) as HTMLDivElement;
+            this._addExport(inspector, actions);
+        }
+
+        public dispose() {
+            // Nothing to dispose
+        }
+
+        private _addExport(inspector: Inspector, actions: HTMLDivElement) {
+            const title = Helpers.CreateDiv('gltf-title', actions);
+            title.textContent = 'Export';
+
+            const name = Helpers.CreateInput('gltf-input', actions);
+            name.placeholder = "File name...";
+
+            const button = Helpers.CreateElement('button', 'gltf-button', actions) as HTMLButtonElement;
+            button.innerText = 'Export GLB';
+
+            button.addEventListener('click', () => {
+                const data = BABYLON.GLTF2Export.GLB(inspector.scene, name.value || "scene", {
+                    shouldExportMesh: mesh => !GLTFTab._IsSkyBox(mesh)
+                });
+
+                if (data) {
+                    data.downloadFiles();
+                }
+            });
+        }
+
+        private static _IsSkyBox(transformNode: BABYLON.TransformNode): boolean {
+            if (transformNode instanceof BABYLON.Mesh) {
+                if (transformNode.material) {
+                    const material = transformNode.material as BABYLON.PBRMaterial | BABYLON.StandardMaterial;
+                    const reflectionTexture = material.reflectionTexture;
+                    if (reflectionTexture && reflectionTexture.coordinatesMode === BABYLON.Texture.SKYBOX_MODE) {
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+    }
+}

+ 1 - 1
inspector/src/tabs/PropertyTab.ts

@@ -101,7 +101,7 @@ module INSPECTOR {
                     node.active(false);
                 }
             }
-            item.getDiv().scrollIntoView();
+          //  item.getDiv().scrollIntoView();
             item.active(true);
         }
 

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

@@ -32,13 +32,15 @@ module INSPECTOR {
             this._tabs.push(this._meshTab);
             this._tabs.push(new LightTab(this, this._inspector));
             this._tabs.push(new MaterialTab(this, this._inspector));
+            if (BABYLON.GLTF2Export) {
+                this._tabs.push(new GLTFTab(this, this._inspector));
+            }
             if (BABYLON.GUI) {
                 this._tabs.push(new GUITab(this, this._inspector));
             }
             this._tabs.push(new PhysicsTab(this, this._inspector));
             this._tabs.push(new CameraTab(this, this._inspector));
             this._tabs.push(new SoundTab(this, this._inspector));
-
             this._toolBar = new Toolbar(this._inspector);
 
             this._build();

+ 9 - 10
loaders/src/glTF/1.0/babylon.glTFLoader.ts

@@ -1568,18 +1568,17 @@ module BABYLON.GLTF1 {
         public compileMaterials = false;
         public useClipPlane = false;
         public compileShadowGenerators = false;
+        public transparencyAsCoverage = false;
+        public preprocessUrlAsync = (url: string) => Promise.resolve(url);
 
-        public onDisposeObservable = new Observable<IGLTFLoader>();
-        public onMeshLoadedObservable = new Observable<AbstractMesh>();
-        public onTextureLoadedObservable = new Observable<BaseTexture>();
-        public onMaterialLoadedObservable = new Observable<Material>();
-        public onCameraLoadedObservable = new Observable<Camera>();
-        public onCompleteObservable = new Observable<IGLTFLoader>();
-        public onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
+        public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
+        public readonly onTextureLoadedObservable = new Observable<BaseTexture>();
+        public readonly onMaterialLoadedObservable = new Observable<Material>();
+        public readonly onCameraLoadedObservable = new Observable<Camera>();
+        public readonly onCompleteObservable = new Observable<IGLTFLoader>();
+        public readonly onDisposeObservable = new Observable<IGLTFLoader>();
+        public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
 
-        /**
-        * State of the loader
-        */
         public state: Nullable<GLTFLoaderState> = null;
 
         public dispose(): void {}

+ 1 - 1
loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts

@@ -25,7 +25,7 @@ module BABYLON.GLTF2.Extensions {
                     const promises = new Array<Promise<void>>();
 
                     const name = material.name || `materialSG_${material._index}`;
-                    const babylonMaterial = this._loader._createMaterial(PBRMaterial, name, babylonDrawMode);
+                    const babylonMaterial = this._loader._createMaterial(name, babylonDrawMode);
 
                     promises.push(this._loader._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                     promises.push(this._loadSpecularGlossinessPropertiesAsync(extensionContext, material, extension, babylonMaterial));

+ 1 - 1
loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts

@@ -15,7 +15,7 @@ module BABYLON.GLTF2.Extensions {
                 let babylonData = material._babylonData[babylonDrawMode];
                 if (!babylonData) {
                     const name = material.name || `materialUnlit_${material._index}`;
-                    const babylonMaterial = this._loader._createMaterial(PBRMaterial, name, babylonDrawMode);
+                    const babylonMaterial = this._loader._createMaterial(name, babylonDrawMode);
                     babylonMaterial.unlit = true;
 
                     const promise = this._loadUnlitPropertiesAsync(context, material, babylonMaterial);

+ 36 - 0
loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts

@@ -0,0 +1,36 @@
+/// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GLTF2.Extensions {
+    const NAME = "MSFT_minecraftMesh";
+
+    /** @hidden */
+    export class MSFT_minecraftMesh extends GLTFLoaderExtension {
+        public readonly name = NAME;
+
+        constructor(loader: GLTFLoader) {
+            super(loader);
+
+            const meshes = loader._gltf.meshes;
+            if (meshes && meshes.length) {
+                for (const mesh of meshes) {
+                    if (mesh && mesh.extras && mesh.extras.MSFT_minecraftMesh) {
+                        this._loader.onMaterialLoadedObservable.add(this._onMaterialLoaded);
+                        break;
+                    }
+                }
+            }
+        }
+
+        private _onMaterialLoaded = (material: PBRMaterial): void => {
+            if (material.needAlphaBlending()) {
+                material.forceDepthWrite = true;
+                material.separateCullingPass = true;
+            }
+
+            material.backFaceCulling = material.forceDepthWrite;
+            material.twoSidedLighting = true;
+        };
+    }
+
+    GLTFLoader._Register(NAME, loader => new MSFT_minecraftMesh(loader));
+}

+ 36 - 0
loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts

@@ -0,0 +1,36 @@
+/// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GLTF2.Extensions {
+    const NAME = "MSFT_sRGBFactors";
+
+    /** @hidden */
+    export class MSFT_sRGBFactors extends GLTFLoaderExtension {
+        public readonly name = NAME;
+
+        constructor(loader: GLTFLoader) {
+            super(loader);
+
+            const materials = loader._gltf.materials;
+            if (materials && materials.length) {
+                for (const material of materials) {
+                    if (material && material.extras && material.extras.MSFT_sRGBFactors) {
+                        this._loader.onMaterialLoadedObservable.add(this._onMaterialLoaded);
+                        break;
+                    }
+                }
+            }
+        }
+
+        private _onMaterialLoaded = (material: PBRMaterial): void => {
+            if (!material.albedoTexture) {
+                material.albedoColor.toLinearSpaceToRef(material.albedoColor);
+            }
+
+            if (!material.reflectivityTexture) {
+                material.reflectivityColor.toLinearSpaceToRef(material.reflectivityColor);
+            }
+        };
+    }
+
+    GLTFLoader._Register(NAME, loader => new MSFT_sRGBFactors(loader));
+}

+ 70 - 57
loaders/src/glTF/2.0/babylon.glTFLoader.ts

@@ -10,12 +10,6 @@ module BABYLON.GLTF2 {
         _total?: number;
     }
 
-    /** @hidden */
-    export interface _MaterialConstructor<T extends Material> {
-        readonly prototype: T;
-        new(name: string, scene: Scene): T;
-    }
-
     /**
      * Loader for loading a glTF 2.0 asset
      */
@@ -39,20 +33,20 @@ module BABYLON.GLTF2 {
         private _progressCallback?: (event: SceneLoaderProgressEvent) => void;
         private _requests = new Array<IFileRequestInfo>();
 
-        private static _Names = new Array<string>();
-        private static _Factories: { [name: string]: (loader: GLTFLoader) => GLTFLoaderExtension } = {};
+        private static _ExtensionNames = new Array<string>();
+        private static _ExtensionFactories: { [name: string]: (loader: GLTFLoader) => GLTFLoaderExtension } = {};
 
         /** @hidden */
         public static _Register(name: string, factory: (loader: GLTFLoader) => GLTFLoaderExtension): void {
-            if (GLTFLoader._Factories[name]) {
+            if (GLTFLoader._ExtensionFactories[name]) {
                 Tools.Error(`Extension with the name '${name}' already exists`);
                 return;
             }
 
-            GLTFLoader._Factories[name] = factory;
+            GLTFLoader._ExtensionFactories[name] = factory;
 
             // Keep the order of registration so that extensions registered first are called first.
-            GLTFLoader._Names.push(name);
+            GLTFLoader._ExtensionNames.push(name);
         }
 
         /**
@@ -81,6 +75,18 @@ module BABYLON.GLTF2 {
         public compileShadowGenerators = false;
 
         /**
+         * Defines if the Alpha blended materials are only applied as coverage. 
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        public transparencyAsCoverage = false;
+
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        public preprocessUrlAsync = (url: string) => Promise.resolve(url);
+
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
@@ -118,7 +124,6 @@ module BABYLON.GLTF2 {
          */
         public readonly onExtensionLoadedObservable = new Observable<IGLTFLoaderExtension>();
 
-
         /**
          * Loader state or null if the loader is not active.
          */
@@ -201,14 +206,13 @@ module BABYLON.GLTF2 {
 
         private _loadAsync(nodes: Nullable<Array<_ILoaderNode>>, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onProgress?: (event: SceneLoaderProgressEvent) => void): Promise<void> {
             return Promise.resolve().then(() => {
-                this._loadExtensions();
-
                 this._babylonScene = scene;
                 this._rootUrl = rootUrl;
                 this._progressCallback = onProgress;
                 this._state = GLTFLoaderState.LOADING;
 
                 this._loadData(data);
+                this._loadExtensions();
                 this._checkExtensions();
 
                 const promises = new Array<Promise<void>>();
@@ -254,23 +258,14 @@ module BABYLON.GLTF2 {
 
                 return resultPromise;
             }).catch(error => {
-                Tools.Error(`glTF Loader: ${error.message}`);
-                this._clear();
-                throw error;
+                if (!this._disposed) {
+                    Tools.Error(`glTF Loader: ${error.message}`);
+                    this._clear();
+                    throw error;
+                }
             });
         }
 
-        private _loadExtensions(): void {
-            for (const name of GLTFLoader._Names) {
-                const extension = GLTFLoader._Factories[name](this);
-                this._extensions[name] = extension;
-
-                this.onExtensionLoadedObservable.notifyObservers(extension);
-            }
-
-            this.onExtensionLoadedObservable.clear();
-        }
-
         private _loadData(data: IGLTFLoaderData): void {
             this._gltf = data.json as _ILoaderGLTF;
             this._setupData();
@@ -324,6 +319,17 @@ module BABYLON.GLTF2 {
             }
         }
 
+        private _loadExtensions(): void {
+            for (const name of GLTFLoader._ExtensionNames) {
+                const extension = GLTFLoader._ExtensionFactories[name](this);
+                this._extensions[name] = extension;
+
+                this.onExtensionLoadedObservable.notifyObservers(extension);
+            }
+
+            this.onExtensionLoadedObservable.clear();
+        }
+
         private _checkExtensions(): void {
             if (this._gltf.extensionsRequired) {
                 for (const name of this._gltf.extensionsRequired) {
@@ -1262,7 +1268,7 @@ module BABYLON.GLTF2 {
         private _getDefaultMaterial(drawMode: number): Material {
             let babylonMaterial = this._defaultBabylonMaterials[drawMode];
             if (!babylonMaterial) {
-                babylonMaterial = this._createMaterial(PBRMaterial, "__gltf_default", drawMode);
+                babylonMaterial = this._createMaterial("__gltf_default", drawMode);
                 babylonMaterial.transparencyMode = PBRMaterial.PBRMATERIAL_OPAQUE;
                 babylonMaterial.metallic = 1;
                 babylonMaterial.roughness = 1;
@@ -1327,7 +1333,7 @@ module BABYLON.GLTF2 {
                 const promises = new Array<Promise<void>>();
 
                 const name = material.name || `materialSG_${material._index}`;
-                const babylonMaterial = this._createMaterial(PBRMaterial, name, babylonDrawMode);
+                const babylonMaterial = this._createMaterial(name, babylonDrawMode);
 
                 promises.push(this._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
                 promises.push(this._loadMaterialMetallicRoughnessPropertiesAsync(context, material, babylonMaterial));
@@ -1350,10 +1356,13 @@ module BABYLON.GLTF2 {
         }
 
         /** @hidden */
-        public _createMaterial<T extends Material>(type: _MaterialConstructor<T>, name: string, drawMode: number): T {
-            const babylonMaterial = new type(name, this._babylonScene);
+        public _createMaterial(name: string, drawMode: number): PBRMaterial {
+            const babylonMaterial = new PBRMaterial(name, this._babylonScene);
             babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
             babylonMaterial.fillMode = drawMode;
+            babylonMaterial.enableSpecularAntiAliasing = true;
+            babylonMaterial.useRadianceOverAlpha = !this.transparencyAsCoverage;
+            babylonMaterial.useSpecularOverAlpha = !this.transparencyAsCoverage;
             return babylonMaterial;
         }
 
@@ -1516,33 +1525,37 @@ module BABYLON.GLTF2 {
                 return Promise.resolve(new Uint8Array(Tools.DecodeBase64(uri)));
             }
 
-            return new Promise((resolve, reject) => {
-                const request = Tools.LoadFile(this._rootUrl + uri, data => {
+            return this.preprocessUrlAsync(this._rootUrl + uri).then(url => {
+                return new Promise<ArrayBufferView>((resolve, reject) => {
                     if (!this._disposed) {
-                        resolve(new Uint8Array(data as ArrayBuffer));
-                    }
-                }, event => {
-                    if (!this._disposed) {
-                        try {
-                            if (request && this._state === GLTFLoaderState.LOADING) {
-                                request._lengthComputable = event.lengthComputable;
-                                request._loaded = event.loaded;
-                                request._total = event.total;
-                                this._onProgress();
+                        const request = Tools.LoadFile(url, data => {
+                            if (!this._disposed) {
+                                resolve(new Uint8Array(data as ArrayBuffer));
                             }
-                        }
-                        catch (e) {
-                            reject(e);
-                        }
-                    }
-                }, this._babylonScene.database, true, (request, exception) => {
-                    if (!this._disposed) {
-                        reject(new LoadFileError(`${context}: Failed to load '${uri}'${request ? ": " + request.status + " " + request.statusText : ""}`, request));
-                    }
-                }) as IFileRequestInfo;
+                        }, event => {
+                            if (!this._disposed) {
+                                try {
+                                    if (request && this._state === GLTFLoaderState.LOADING) {
+                                        request._lengthComputable = event.lengthComputable;
+                                        request._loaded = event.loaded;
+                                        request._total = event.total;
+                                        this._onProgress();
+                                    }
+                                }
+                                catch (e) {
+                                    reject(e);
+                                }
+                            }
+                        }, this._babylonScene.database, true, (request, exception) => {
+                            if (!this._disposed) {
+                                reject(new LoadFileError(`${context}: Failed to load '${uri}'${request ? ": " + request.status + " " + request.statusText : ""}`, request));
+                            }
+                        }) as IFileRequestInfo;
 
-                this._requests.push(request);
-            })
+                        this._requests.push(request);
+                    }
+                });
+            });
         }
 
         private _onProgress(): void {
@@ -1762,7 +1775,7 @@ module BABYLON.GLTF2 {
 
         /** @hidden */
         public _applyExtensions<T>(actionAsync: (extension: GLTFLoaderExtension) => Nullable<Promise<T>>) {
-            for (const name of GLTFLoader._Names) {
+            for (const name of GLTFLoader._ExtensionNames) {
                 const extension = this._extensions[name];
                 if (extension.enabled) {
                     const promise = actionAsync(extension);

+ 28 - 0
loaders/src/glTF/babylon.glTFFileLoader.ts

@@ -116,6 +116,18 @@ module BABYLON {
         compileShadowGenerators: boolean;
 
         /**
+         * Defines if the Alpha blended materials are only applied as coverage. 
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        transparencyAsCoverage: boolean;
+
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        preprocessUrlAsync: (url: string) => Promise<string>;
+
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         onMeshLoadedObservable: Observable<AbstractMesh>;
@@ -249,6 +261,18 @@ module BABYLON {
         public compileShadowGenerators = false;
 
         /**
+         * Defines if the Alpha blended materials are only applied as coverage. 
+         * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials.
+         * If true, no extra effects are applied to transparent pixels.
+         */
+        public transparencyAsCoverage = false;
+
+        /**
+         * Function called before loading a url referenced by the asset.
+         */
+        public preprocessUrlAsync = (url: string) => Promise.resolve(url);
+
+        /**
          * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh.
          */
         public readonly onMeshLoadedObservable = new Observable<AbstractMesh>();
@@ -415,6 +439,8 @@ module BABYLON {
                 this._loader = null;
             }
 
+            this.preprocessUrlAsync = url => Promise.resolve(url);
+
             this.onMeshLoadedObservable.clear();
             this.onTextureLoadedObservable.clear();
             this.onMaterialLoadedObservable.clear();
@@ -560,6 +586,8 @@ module BABYLON {
             loader.compileMaterials = this.compileMaterials;
             loader.useClipPlane = this.useClipPlane;
             loader.compileShadowGenerators = this.compileShadowGenerators;
+            loader.transparencyAsCoverage = this.transparencyAsCoverage;
+            loader.preprocessUrlAsync = this.preprocessUrlAsync;
             loader.onMeshLoadedObservable.add(mesh => this.onMeshLoadedObservable.notifyObservers(mesh));
             loader.onTextureLoadedObservable.add(texture => this.onTextureLoadedObservable.notifyObservers(texture));
             loader.onMaterialLoadedObservable.add(material => this.onMaterialLoadedObservable.notifyObservers(material));

+ 1 - 1
package.json

@@ -9,7 +9,7 @@
     ],
     "name": "babylonjs",
     "description": "Babylon.js is a JavaScript 3D engine based on webgl.",
-    "version": "3.2.0-beta.5",
+    "version": "3.2.0-rc.1",
     "repository": {
         "type": "git",
         "url": "https://github.com/BabylonJS/Babylon.js.git"

+ 8 - 1
src/Engine/babylon.engine.ts

@@ -726,7 +726,7 @@
          * Returns the current version of the framework
          */
         public static get Version(): string {
-            return "3.2.0-beta.5";
+            return "3.2.0-rc.1";
         }
 
         // Updatable statics so stick with vars here
@@ -782,6 +782,11 @@
          **/
         public enableOfflineSupport = false;
 
+        /** 
+         * Gets or sets a boolean to enable/disable checking manifest if IndexedDB support is enabled (Babylon.js will always consider the database is up to date)
+         **/
+        public disableManifestCheck = false;        
+
         /**
          * Gets the list of created scenes
          */
@@ -7095,6 +7100,8 @@
                 switch(format) {
                     case Engine.TEXTUREFORMAT_LUMINANCE:
                         return this._gl.LUMINANCE;
+                    case Engine.TEXTUREFORMAT_RGB:
+                        return this._gl.RGB;                        
                 }                    
             }
             return this._gl.RGBA;

+ 3 - 2
src/Loading/babylon.sceneLoader.ts

@@ -309,7 +309,8 @@
             }
 
             if (rootUrl.indexOf("file:") === -1) {
-                let canUseOfflineSupport = scene.getEngine().enableOfflineSupport;
+                let engine = scene.getEngine();
+                let canUseOfflineSupport = engine.enableOfflineSupport;
                 if (canUseOfflineSupport) {
                     // Also check for exceptions
                     let exceptionFound = false;
@@ -325,7 +326,7 @@
 
                 if (canUseOfflineSupport) {
                     // Checking if a manifest file has been set for this scene and if offline mode has been requested
-                    database = new Database(rootUrl + sceneFilename, manifestChecked);
+                    database = new Database(rootUrl + sceneFilename, manifestChecked, engine.disableManifestCheck);
                 }
                 else {
                     manifestChecked();

+ 2 - 2
src/Materials/PBR/babylon.pbrBaseMaterial.ts

@@ -132,7 +132,7 @@
 
         public FORCENORMALFORWARD = false;
 
-        public GEOMETRYAA = false;
+        public SPECULARAA = false;
 
         public UNLIT = false;
 
@@ -1211,7 +1211,7 @@
                 defines.ALPHAFRESNEL = this._useAlphaFresnel || this._useLinearAlphaFresnel;
                 defines.LINEARALPHAFRESNEL = this._useLinearAlphaFresnel;
 
-                defines.GEOMETRYAA = scene.getEngine().getCaps().standardDerivatives && this._enableSpecularAntiAliasing;
+                defines.SPECULARAA = scene.getEngine().getCaps().standardDerivatives && this._enableSpecularAntiAliasing;
             }
 
             if (defines._areImageProcessingDirty) {

+ 4 - 2
src/Materials/Textures/babylon.videoTexture.ts

@@ -32,6 +32,7 @@
 
         private _generateMipMaps: boolean;
         private _engine: Engine;
+        private _stillImageCaptured = false;
 
         /**
          * Creates a video texture.
@@ -141,8 +142,8 @@
             );
 
             this._texture.isReady = true;
-            this._updateInternalTexture();
 
+            this._updateInternalTexture();
             if (this._onLoadObservable && this._onLoadObservable.hasObservers()) {
                 this.onLoadObservable.notifyObservers(this);
             }
@@ -183,9 +184,10 @@
             if (!isVisible) {
                 return;
             }
-            if (this.video.paused) {
+            if (this.video.paused && this._stillImageCaptured) {
                 return;
             }
+            this._stillImageCaptured = true;
             this._updateInternalTexture();
         }
 

+ 3 - 5
src/Shaders/ShadersInclude/pbrFunctions.fx

@@ -137,11 +137,9 @@ float environmentRadianceOcclusion(float ambientOcclusion, float NdotVUnclamped)
     return clamp(square(temp) - 1.0 + ambientOcclusion, 0.0, 1.0);
 }
 
-float environmentHorizonOcclusion(vec3 reflection, vec3 normal) {
-	// http://marmosetco.tumblr.com/post/81245981087
-#ifdef REFLECTIONMAP_OPPOSITEZ
-    reflection.z *= -1.0;
-#endif
+float environmentHorizonOcclusion(vec3 view, vec3 normal) {
+    // http://marmosetco.tumblr.com/post/81245981087
+    vec3 reflection = reflect(view, normal);
     float temp = clamp( 1.0 + 1.1 * dot(reflection, normal), 0.0, 1.0);
     return square(temp);
 }

+ 6 - 6
src/Shaders/pbr.fragment.fx

@@ -1,4 +1,4 @@
-#if defined(BUMP) || !defined(NORMAL) || defined(FORCENORMALFORWARD) || defined(GEOMETRYAA)
+#if defined(BUMP) || !defined(NORMAL) || defined(FORCENORMALFORWARD) || defined(SPECULARAA)
 #extension GL_OES_standard_derivatives : enable
 #endif
 
@@ -226,7 +226,9 @@ void main(void) {
     vec3 normalW = normalize(cross(dFdx(vPositionW), dFdy(vPositionW))) * vEyePosition.w;
 #endif
 
-#ifdef GEOMETRYAA
+#include<bumpFragment>
+
+#ifdef SPECULARAA
     vec3 nDfdx = dFdx(normalW.xyz);
     vec3 nDfdy = dFdy(normalW.xyz);
     float slopeSquare = max(dot(nDfdx, nDfdx), dot(nDfdy, nDfdy));
@@ -238,8 +240,6 @@ void main(void) {
     float geometricRoughnessFactor = 0.;
 #endif
 
-#include<bumpFragment>
-
 #if defined(FORCENORMALFORWARD) && defined(NORMAL)
     vec3 faceNormal = normalize(cross(dFdx(vPositionW), dFdy(vPositionW))) * vEyePosition.w;
     #if defined(TWOSIDEDLIGHTING)
@@ -434,7 +434,7 @@ void main(void) {
         float NdotV = clamp(NdotVUnclamped,0., 1.) + 0.00001;
         float alphaG = convertRoughnessToAverageSlope(roughness);
 
-        #ifdef GEOMETRYAA
+        #ifdef SPECULARAA
             // Adapt linear roughness (alphaG) to geometric curvature of the current pixel.
             // 75% accounts a bit for the bigger tail linked to Gaussian Filtering.
             alphaG += (0.75 * geometricAlphaGFactor);
@@ -660,7 +660,7 @@ void main(void) {
         #ifdef HORIZONOCCLUSION
             #ifdef BUMP
                 #ifdef REFLECTIONMAP_3D
-                    float eho = environmentHorizonOcclusion(reflectionCoords, normalW);
+                    float eho = environmentHorizonOcclusion(-viewDirectionW, normalW);
                     specularEnvironmentReflectance *= eho;
                 #endif
             #endif

+ 56 - 9
src/Tools/babylon.database.ts

@@ -1,4 +1,8 @@
 module BABYLON {
+    /**
+     * Class used to enable access to IndexedDB
+     * @see @https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
+     */
     export class Database {
         private callbackManifestChecked: (check: boolean) => any;
         private currentSceneUrl: string;
@@ -13,20 +17,35 @@ module BABYLON {
         // Handling various flavors of prefixed version of IndexedDB
         private idbFactory = <IDBFactory>(window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB);
 
+        /** Gets a boolean indicating if the user agent supports blob storage (this value will be updated after creating the first Database object) */
         static IsUASupportingBlobStorage = true;
+
+        /** Gets a boolean indicating if Database storate is enabled */
         static IDBStorageEnabled = true;
 
+        /**
+         * Gets a boolean indicating if scene must be saved in the database
+         */
         public get enableSceneOffline(): boolean {
             return this._enableSceneOffline;
         }
 
+        /**
+         * Gets a boolean indicating if textures must be saved in the database
+         */
         public get enableTexturesOffline(): boolean {
             return this._enableTexturesOffline;
         }
 
-        constructor(urlToScene: string, callbackManifestChecked: (checked: boolean) => any) {
+        /**
+         * Creates a new Database
+         * @param urlToScene defines the url to load the scene
+         * @param callbackManifestChecked defines the callback to use when manifest is checked
+         * @param disableManifestCheck defines a boolean indicating that we want to skip the manifest validation (it will be considered validated and up to date)
+         */
+        constructor(urlToScene: string, callbackManifestChecked: (checked: boolean) => any, disableManifestCheck = false) {
             this.callbackManifestChecked = callbackManifestChecked;
-            this.currentSceneUrl = Database.ReturnFullUrlLocation(urlToScene);
+            this.currentSceneUrl = Database._ReturnFullUrlLocation(urlToScene);
             this.db = null;
             this._enableSceneOffline = false;
             this._enableTexturesOffline = false;
@@ -37,11 +56,21 @@ module BABYLON {
             if (!Database.IDBStorageEnabled) {
                 this.callbackManifestChecked(true);
             } else {
-                this.checkManifestFile();
+                if (disableManifestCheck) {
+                    this._enableSceneOffline = true;
+                    this._enableTexturesOffline = true;
+                    this.manifestVersionFound = 1;
+                    Tools.SetImmediate(() => {
+                        this.callbackManifestChecked(true);
+                    });
+                }
+                else {
+                    this._checkManifestFile();
+                }
             }
         }
 
-        static parseURL = (url: string) => {
+        private static _ParseURL = (url: string) => {
             var a = document.createElement('a');
             a.href = url;
             var urlWithoutHash = url.substring(0, url.lastIndexOf("#"));
@@ -50,16 +79,16 @@ module BABYLON {
             return absLocation;
         }
 
-        static ReturnFullUrlLocation = (url: string): string => {
+        private static _ReturnFullUrlLocation = (url: string): string => {
             if (url.indexOf("http:/") === -1 && url.indexOf("https:/") === -1) {
-                return (Database.parseURL(window.location.href) + url);
+                return (Database._ParseURL(window.location.href) + url);
             }
             else {
                 return url;
             }
         }
 
-        public checkManifestFile() {
+        private _checkManifestFile() {
             var noManifestFile = () => {
                 this._enableSceneOffline = false;
                 this._enableTexturesOffline = false;
@@ -123,6 +152,11 @@ module BABYLON {
             }
         }
 
+        /**
+         * Open the database and make it available
+         * @param successCallback defines the callback to call on success
+         * @param errorCallback defines the callback to call on error
+         */
         public openAsync(successCallback: () => void, errorCallback: () => void) {
             let handleError = () => {
                 this.isSupported = false;
@@ -182,8 +216,13 @@ module BABYLON {
             }
         }
 
+        /**
+         * Loads an image from the database
+         * @param url defines the url to load from
+         * @param image defines the target DOM image
+         */
         public loadImageFromDB(url: string, image: HTMLImageElement) {
-            var completeURL = Database.ReturnFullUrlLocation(url);
+            var completeURL = Database._ReturnFullUrlLocation(url);
 
             var saveAndLoadImage = () => {
                 if (!this.hasReachedQuota && this.db !== null) {
@@ -442,8 +481,16 @@ module BABYLON {
             }
         }
 
+        /**
+         * Loads a file from database
+         * @param url defines the URL to load from
+         * @param sceneLoaded defines a callback to call on success
+         * @param progressCallBack defines a callback to call when progress changed
+         * @param errorCallback defines a callback to call on error
+         * @param useArrayBuffer defines a boolean to use array buffer instead of text string
+         */
         public loadFileFromDB(url: string, sceneLoaded: (data: any) => void, progressCallBack?: (data: any) => void, errorCallback?: () => void, useArrayBuffer?: boolean) {
-            var completeUrl = Database.ReturnFullUrlLocation(url);
+            var completeUrl = Database._ReturnFullUrlLocation(url);
 
             var saveAndLoadFile = () => {
                 // the scene is not yet in the DB, let's try to save it

+ 48 - 0
tests/unit/babylon/src/Loading/babylon.sceneLoader.tests.ts

@@ -367,6 +367,54 @@ describe('Babylon Scene Loader', function () {
             });
         });
 
+        it('Load BoomBox with transparencyAsCoverage', () => {
+            const scene = new BABYLON.Scene(subject);
+
+            const promises = new Array<Promise<any>>();
+
+            BABYLON.SceneLoader.OnPluginActivatedObservable.add((loader: BABYLON.GLTFFileLoader) => {
+                var specularOverAlpha = false;
+                var radianceOverAlpha = false;
+
+                loader.transparencyAsCoverage = true;
+                loader.onMaterialLoaded = material => {
+                    specularOverAlpha = specularOverAlpha || (material as BABYLON.PBRMaterial).useSpecularOverAlpha;
+                    radianceOverAlpha = radianceOverAlpha || (material as BABYLON.PBRMaterial).useRadianceOverAlpha;
+                };
+                promises.push(loader.whenCompleteAsync().then(() => {
+                    expect(specularOverAlpha, "specularOverAlpha").to.be.false;
+                    expect(radianceOverAlpha, "radianceOverAlpha").to.be.false;
+                }));
+            }, undefined, undefined, undefined, true);
+
+            promises.push(BABYLON.SceneLoader.AppendAsync("/Playground/scenes/BoomBox/", "BoomBox.gltf", scene));
+            return Promise.all(promises);
+        });
+
+        it('Load BoomBox without transparencyAsCoverage', () => {
+            const scene = new BABYLON.Scene(subject);
+
+            const promises = new Array<Promise<any>>();
+
+            BABYLON.SceneLoader.OnPluginActivatedObservable.add((loader: BABYLON.GLTFFileLoader) => {
+                var specularOverAlpha = true;
+                var radianceOverAlpha = true;
+
+                loader.transparencyAsCoverage = false;
+                loader.onMaterialLoaded = material => {
+                    specularOverAlpha = specularOverAlpha && (material as BABYLON.PBRMaterial).useSpecularOverAlpha;
+                    radianceOverAlpha = radianceOverAlpha && (material as BABYLON.PBRMaterial).useRadianceOverAlpha;
+                };
+                promises.push(loader.whenCompleteAsync().then(() => {
+                    expect(specularOverAlpha, "specularOverAlpha").to.be.true;
+                    expect(radianceOverAlpha, "radianceOverAlpha").to.be.true;
+                }));
+            }, undefined, undefined, undefined, true);
+
+            promises.push(BABYLON.SceneLoader.AppendAsync("/Playground/scenes/BoomBox/", "BoomBox.gltf", scene));
+            return Promise.all(promises);
+        });
+
         // TODO: test animation group callback
         // TODO: test material instancing
         // TODO: test ImportMesh with specific node name