Browse Source

Add glTF 2.0 support
- Breaks animation and materials common extension
- KHR_technique_webgl still to be added

Gary Hsu 8 years ago
parent
commit
d1aff9b88b

+ 2 - 2
Tools/Gulp/config.json

@@ -438,8 +438,8 @@
         "../../loaders/src/glTF/babylon.glTFFileLoader.ts",
         "../../loaders/src/glTF/babylon.glTFFileLoaderUtils.ts",
         "../../loaders/src/glTF/babylon.glTFFileLoaderExtension.ts",
-        "../../loaders/src/glTF/babylon.glTFBinaryExtension.ts",
-        "../../loaders/src/glTF/babylon.glTFMaterialCommonExtension.ts"
+        "../../loaders/src/glTF/babylon.glTFMaterialsCommonExtension.ts",
+        "../../loaders/src/glTF/babylon.glTFMaterialsPbrSpecularGlossinessExtension.ts"
       ],
       "output": "babylon.glTFFileLoader.js"
     }],

+ 0 - 177
loaders/src/glTF/babylon.glTFBinaryExtension.ts

@@ -1,177 +0,0 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
-
-module BABYLON {
-    const BinaryExtensionBufferName = "binary_glTF";
-
-    enum EContentFormat {
-        JSON = 0
-    };
-
-    interface IGLTFBinaryExtension {
-        content: Object;
-        body: Uint8Array;
-    };
-
-    interface IGLTFBinaryExtensionShader {
-        bufferView: string;
-    };
-
-    interface IGLTFBinaryExtensionImage {
-        bufferView: string;
-        mimeType: string;
-        height: number;
-        width: number;
-    };
-
-    export class GLTFBinaryExtension extends GLTFFileLoaderExtension {
-        private _binary: IGLTFBinaryExtension;
-
-        public constructor() {
-            super("KHR_binary_glTF");
-        }
-
-        public loadRuntimeAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): boolean {
-            if (!(data instanceof ArrayBuffer)) {
-                return false;
-            }
-
-            setTimeout(() => {
-                this._binary = this._parseBinary(<ArrayBuffer>data);
-                if (!this._binary) {
-                    onError();
-                    return true;
-                }
-
-                var gltfRuntime = GLTFFileLoaderBase.CreateRuntime(this._binary.content, scene, rootUrl);
-
-                if (gltfRuntime.extensionsUsed.indexOf(this.name) === -1) {
-                    Tools.Warn("glTF binary file does not have " + this.name + " specified in extensionsUsed");
-                    gltfRuntime.extensionsUsed.push(this.name);
-                }
-
-                onSuccess(gltfRuntime);
-            });
-
-            return true;
-        }
-
-        public loadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): boolean {
-            if (gltfRuntime.extensionsUsed.indexOf(this.name) === -1) {
-                return false;
-            }
-
-            if (id !== BinaryExtensionBufferName) {
-                return false;
-            }
-
-            onSuccess(this._binary.body);
-            return true;
-        }
-
-        public loadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): boolean {
-            var texture: IGLTFTexture = gltfRuntime.textures[id];
-            var source: IGLTFImage = gltfRuntime.images[texture.source];
-            if (!source.extensions || !(this.name in source.extensions)) {
-                return false;
-            }
-
-            var sourceExt: IGLTFBinaryExtensionImage = source.extensions[this.name];
-            var bufferView: IGLTFBufferView = gltfRuntime.bufferViews[sourceExt.bufferView];
-            var buffer = GLTFUtils.GetBufferFromBufferView(gltfRuntime, bufferView, 0, bufferView.byteLength, EComponentType.UNSIGNED_BYTE);
-            onSuccess(buffer);
-            return true;
-        }
-
-        public loadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: () => void): boolean {
-            var shader: IGLTFShader = gltfRuntime.shaders[id];
-            if (!shader.extensions || !(this.name in shader.extensions)) {
-                return false;
-            }
-
-            var binaryExtensionShader: IGLTFBinaryExtensionShader = shader.extensions[this.name];
-            var bufferView: IGLTFBufferView = gltfRuntime.bufferViews[binaryExtensionShader.bufferView];
-            var shaderBytes = GLTFUtils.GetBufferFromBufferView(gltfRuntime, bufferView, 0, bufferView.byteLength, EComponentType.UNSIGNED_BYTE);
-
-            setTimeout(() => {
-                var shaderString = GLTFUtils.DecodeBufferToText(shaderBytes);
-                onSuccess(shaderString);
-            });
-
-            return true;
-        }
-
-        // Parses a glTF binary array buffer into its content and body
-        private _parseBinary(data: ArrayBuffer): IGLTFBinaryExtension {
-            var binaryReader = new BinaryReader(data);
-
-            var magic = GLTFUtils.DecodeBufferToText(binaryReader.getUint8Array(4));
-            if (magic != "glTF") {
-                Tools.Error("Unexpected magic: " + magic);
-                return null;
-            }
-
-            var version = binaryReader.getUint32();
-            if (version != 1) {
-                Tools.Error("Unsupported version: " + version);
-                return null;
-            }
-
-            var length = binaryReader.getUint32();
-            if (length != data.byteLength) {
-                Tools.Error("Length in header does not match actual data length: " + length + " != " + data.byteLength);
-                return null;
-            }
-
-            var contentLength = binaryReader.getUint32();
-            var contentFormat = <EContentFormat>binaryReader.getUint32();
-
-            var content: Object;
-            switch (contentFormat) {
-                case EContentFormat.JSON:
-                    var jsonText = GLTFUtils.DecodeBufferToText(binaryReader.getUint8Array(contentLength));
-                    content = JSON.parse(jsonText);
-                    break;
-                default:
-                    Tools.Error("Unexpected content format: " + contentFormat);
-                    return null;
-            }
-
-            var body = binaryReader.getUint8Array();
-
-            return {
-                content: content,
-                body: body
-            };
-        };
-    }
-
-    class BinaryReader {
-        private _arrayBuffer: ArrayBuffer;
-        private _dataView: DataView;
-        private _byteOffset: number;
-
-        constructor(arrayBuffer: ArrayBuffer) {
-            this._arrayBuffer = arrayBuffer;
-            this._dataView = new DataView(arrayBuffer);
-            this._byteOffset = 0;
-        }
-
-        public getUint32(): number {
-            var value = this._dataView.getUint32(this._byteOffset, true);
-            this._byteOffset += 4;
-            return value;
-        }
-
-        public getUint8Array(length?: number): Uint8Array {
-            if (!length) {
-                length = this._arrayBuffer.byteLength - this._byteOffset;
-            }
-
-            var value = new Uint8Array(this._arrayBuffer, this._byteOffset, length);
-            this._byteOffset += length;
-            return value;
-        }
-    }
-
-    GLTFFileLoader.RegisterExtension(new GLTFBinaryExtension());
-}

File diff suppressed because it is too large
+ 515 - 1033
loaders/src/glTF/babylon.glTFFileLoader.ts


+ 21 - 123
loaders/src/glTF/babylon.glTFFileLoaderExtension.ts

@@ -12,141 +12,39 @@ module BABYLON {
             return this._name;
         }
 
-        /**
-        * Defines an override for loading the runtime
-        * Return true to stop further extensions from loading the runtime
-        */
-        public loadRuntimeAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): boolean {
-            return false;
-        }
-
-        /**
-         * Defines an onverride for creating gltf runtime
-         * Return true to stop further extensions from creating the runtime
-         */
-        public loadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError: () => void): boolean {
-            return false;
-        }
-
-        /**
-        * Defines an override for loading buffers
-        * Return true to stop further extensions from loading this buffer
-        */
-        public loadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): boolean {
-            return false;
-        }
-
-        /**
-        * Defines an override for loading texture buffers
-        * Return true to stop further extensions from loading this texture data
-        */
-        public loadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): boolean {
-            return false;
-        }
+        protected postCreateRuntime(runtime: IGLTFRuntime): void {}
 
-        /**
-        * Defines an override for creating textures
-        * Return true to stop further extensions from loading this texture
-        */
-        public createTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: () => void): boolean {
-            return false;
-        }
-
-        /**
-        * Defines an override for loading shader strings
-        * Return true to stop further extensions from loading this shader data
-        */
-        public loadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: () => void): boolean {
-            return false;
-        }
-
-        /**
-        * Defines an override for loading materials
-        * Return true to stop further extensions from loading this material
-        */
-        public loadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): boolean {
-            return false;
-        }
+        // Return true to stop other extensions from loading materials.
+        protected loadMaterial(runtime: IGLTFRuntime, index: number): boolean { return false; }
 
         // ---------
         // Utilities
         // ---------
 
-        public static LoadRuntimeAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
-                return loaderExtension.loadRuntimeAsync(scene, data, rootUrl, onSuccess, onError);
-            }, () => {
-                setTimeout(() => {
-                    onSuccess(GLTFFileLoaderBase.CreateRuntime(JSON.parse(<string>data), scene, rootUrl));
-                });
-            });
-        }
-
-        public static LoadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
-                return loaderExtension.loadRuntimeExtensionsAsync(gltfRuntime, onSuccess, onError);
-            }, () => {
-                setTimeout(() => {
-                    onSuccess();
-                });
-            });
-        }
-
-        public static LoadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (bufferView: ArrayBufferView) => void, onError: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
-                return loaderExtension.loadBufferAsync(gltfRuntime, id, onSuccess, onError);
-            }, () => {
-                GLTFFileLoaderBase.LoadBufferAsync(gltfRuntime, id, onSuccess, onError);
-            });
-        }
-
-        public static LoadTextureAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (texture: Texture) => void, onError: () => void): void {
-            GLTFFileLoaderExtension.LoadTextureBufferAsync(gltfRuntime, id,
-                buffer => GLTFFileLoaderExtension.CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError),
-                onError);
-        }
-
-        public static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderData: string) => void, onError: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
-                return loaderExtension.loadShaderStringAsync(gltfRuntime, id, onSuccess, onError);
-            }, () => {
-                GLTFFileLoaderBase.LoadShaderStringAsync(gltfRuntime, id, onSuccess, onError);
-            });
-        }
-
-        public static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
-                return loaderExtension.loadMaterialAsync(gltfRuntime, id, onSuccess, onError);
-            }, () => {
-                GLTFFileLoaderBase.LoadMaterialAsync(gltfRuntime, id, onSuccess, onError);
-            });
-        }
-
-        private static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
-                return loaderExtension.loadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);
-            }, () => {
-                GLTFFileLoaderBase.LoadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);
-            });
-        }
-
-        private static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
-                return loaderExtension.createTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);
-            }, () => {
-                GLTFFileLoaderBase.CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);
-            });
+        public static PostCreateRuntime(runtime: IGLTFRuntime): void {
+            for (var extensionName in GLTFFileLoader.Extensions) {
+                var extension = GLTFFileLoader.Extensions[extensionName];
+                if (extension.postCreateRuntime) {
+                    extension.postCreateRuntime(runtime);
+                }
+            }
         }
 
-        private static ApplyExtensions(func: (loaderExtension: GLTFFileLoaderExtension) => boolean, defaultFunc: () => void): void {
+        public static LoadMaterial(runtime: IGLTFRuntime, index: number): void {
             for (var extensionName in GLTFFileLoader.Extensions) {
-                var loaderExtension = GLTFFileLoader.Extensions[extensionName];
-                if (func(loaderExtension)) {
-                    return;
+                var extension = GLTFFileLoader.Extensions[extensionName];
+                if (extension.loadMaterial) {
+                    if (extension.loadMaterial(runtime, index)) {
+                        return;
+                    }
                 }
             }
 
-            defaultFunc();
+            var material = GLTFFileLoader.LoadMaterial(runtime, index);
+            if (material) {
+                GLTFFileLoader.LoadMetallicRoughnessMaterialProperties(runtime, material);
+                GLTFFileLoader.LoadCommonMaterialProperties(runtime, material);
+            }
         }
     }
 }

+ 168 - 223
loaders/src/glTF/babylon.glTFFileLoaderInterfaces.ts

@@ -4,6 +4,15 @@ module BABYLON {
     /**
     * Enums
     */
+    export enum EBinaryContentFormat {
+        JSON = 0
+    }
+
+    export enum EBufferViewTarget {
+        ARRAY_BUFFER = 34962,
+        ELEMENT_ARRAY_BUFFER = 34963
+    }
+
     export enum EComponentType {
         BYTE = 5120,
         UNSIGNED_BYTE = 5121,
@@ -12,9 +21,14 @@ module BABYLON {
         FLOAT = 5126
     }
 
-    export enum EShaderType {
-        FRAGMENT = 35632,
-        VERTEX = 35633
+    export enum EMeshPrimitiveMode {
+        POINTS = 0,
+        LINES = 1,
+        LINE_LOOP = 2,
+        LINE_STRIP = 3,
+        TRIANGLES = 4,
+        TRIANGLE_STRIP = 5,
+        TRIANGLE_FAN = 6
     }
 
     export enum EParameterType {
@@ -41,13 +55,12 @@ module BABYLON {
         SAMPLER_2D = 35678
     }
 
-    export enum ETextureWrapMode {
-        CLAMP_TO_EDGE = 33071,
-        MIRRORED_REPEAT = 33648,
-        REPEAT = 10497
+    export enum ETextureMagFilter {
+        NEAREST = 9728,
+        LINEAR = 9728,
     }
 
-    export enum ETextureFilterType {
+    export enum ETextureMinFilter {
         NEAREST = 9728,
         LINEAR = 9728,
         NEAREST_MIPMAP_NEAREST = 9984,
@@ -64,28 +77,21 @@ module BABYLON {
         LUMINANCE_ALPHA = 6410
     }
 
-    export enum ECullingType {
-        FRONT = 1028,
-        BACK = 1029,
-        FRONT_AND_BACK = 1032
+    export enum ETextureTarget {
+        TEXTURE_2D = 3553
     }
 
-    export enum EBlendingFunction {
-        ZERO = 0,
-        ONE = 1,
-        SRC_COLOR = 768,
-        ONE_MINUS_SRC_COLOR = 769,
-        DST_COLOR = 774,
-        ONE_MINUS_DST_COLOR = 775,
-        SRC_ALPHA = 770,
-        ONE_MINUS_SRC_ALPHA = 771,
-        DST_ALPHA = 772,
-        ONE_MINUS_DST_ALPHA = 773,
-        CONSTANT_COLOR = 32769,
-        ONE_MINUS_CONSTANT_COLOR = 32770,
-        CONSTANT_ALPHA = 32771,
-        ONE_MINUS_CONSTANT_ALPHA = 32772,
-        SRC_ALPHA_SATURATE = 776
+    export enum ETextureType {
+        UNSIGNED_BYTE = 5121,
+        UNSIGNED_SHORT_5_6_5 = 33635,
+        UNSIGNED_SHORT_4_4_4_4 = 32819,
+        UNSIGNED_SHORT_5_5_5_1 = 32820
+    }
+
+    export enum ETextureWrapMode {
+        CLAMP_TO_EDGE = 33071,
+        MIRRORED_REPEAT = 33648,
+        REPEAT = 10497
     }
 
     /**
@@ -93,7 +99,7 @@ module BABYLON {
     */
     export interface IGLTFProperty {
         extensions?: Object;
-        extras?: Object;
+        extras?: any;
     }
 
     export interface IGLTFChildRootProperty extends IGLTFProperty {
@@ -101,152 +107,63 @@ module BABYLON {
     }
 
     export interface IGLTFAccessor extends IGLTFChildRootProperty {
-        bufferView: string;
+        bufferView: number;
         byteOffset: number;
-        byteStride: number;
+        byteStride?: number;
+        componentType: EComponentType;
+        normalized?: boolean;
         count: number;
         type: string;
-        componentType: EComponentType;
-
-        max?: number[],
-        min?: number[],
-        name?: string;
-    }
-
-    export interface IGLTFBufferView extends IGLTFChildRootProperty {
-        buffer: string;
-        byteOffset: number;
-        byteLength: number;
-
-        target?: number;
-    }
-
-    export interface IGLTFBuffer extends IGLTFChildRootProperty {
-        uri: string;
-
-        byteLength?: number;
-        type?: string;
+        max: number[];
+        min: number[];
     }
 
-    export interface IGLTFShader extends IGLTFChildRootProperty {
-        uri: string;
-        type: EShaderType;
-    }
-
-    export interface IGLTFProgram extends IGLTFChildRootProperty {
-        attributes: string[];
-        fragmentShader: string;
-        vertexShader: string;
-    }
-
-    export interface IGLTFTechniqueParameter {
-        type: number;
-
-        count?: number;
-        semantic?: string;
-        node?: string;
-        value?: number|boolean|string|Array<any>;
-        source?: string;
-
-        babylonValue?: any;
-    }
-
-    export interface IGLTFTechniqueCommonProfile {
-        lightingModel: string;
-        texcoordBindings: Object;
-
-        parameters?: Array<any>;
-    }
-
-    export interface IGLTFTechniqueStatesFunctions {
-        blendColor?: number[];
-        blendEquationSeparate?: number[];
-        blendFuncSeparate?: number[];
-        colorMask: boolean[];
-        cullFace: number[];
-    }
-
-    export interface IGLTFTechniqueStates {
-        enable: number[];
-        functions: IGLTFTechniqueStatesFunctions;
-    }
-
-    export interface IGLTFTechnique extends IGLTFChildRootProperty {
-        parameters: Object;
-        program: string;
-
-        attributes: Object;
-        uniforms: Object;
-        states: IGLTFTechniqueStates;
-    }
-
-    export interface IGLTFMaterial extends IGLTFChildRootProperty {
-        technique?: string;
-        values: string[];
-    }
-
-    export interface IGLTFMeshPrimitive extends IGLTFProperty {
-        attributes: Object;
-        indices: string;
-        material: string;
-
-        mode?: number;
-    }
-
-    export interface IGLTFMesh extends IGLTFChildRootProperty {
-        primitives: IGLTFMeshPrimitive[];
+    export interface IGLTFAnimationChannel {
+        sampler: number;
+        target: IGLTFAnimationChannelTarget;
     }
 
-    export interface IGLTFImage extends IGLTFChildRootProperty {
-        uri: string;
+    export interface IGLTFAnimationChannelTarget {
+        id: number;
+        path: string;
     }
 
-    export interface IGLTFSampler extends IGLTFChildRootProperty {
-        magFilter?: number;
-        minFilter?: number;
-        wrapS?: number;
-        wrapT?: number;
+    export interface IGLTFAnimationSampler {
+        input: number;
+        interpolation?: string;
+        output: number;
     }
 
-    export interface IGLTFTexture extends IGLTFChildRootProperty {
-        sampler: string;
-        source: string;
-
-        format?: ETextureFormat;
-        internalFormat?: ETextureFormat;
-        target?: number;
-        type?: number;
-        
-        // Babylon.js values (optimize)
-        babylonTexture?: Texture;
+    export interface IGLTFAnimation extends IGLTFChildRootProperty {
+        channels?: IGLTFAnimationChannel[];
+        samplers?: IGLTFAnimationSampler[];
     }
 
-    export interface IGLTFAmbienLight {
-        color?: number[];
+    export interface IGLTFAssetProfile extends IGLTFProperty {
+        api?: string;
+        version?: string;
     }
 
-    export interface IGLTFDirectionalLight {
-        color?: number[];
+    export interface IGLTFAsset extends IGLTFChildRootProperty {
+        copyright?: string;
+        generator?: string;
+        profile?: IGLTFAssetProfile;
+        version: string;
     }
 
-    export interface IGLTFPointLight {
-        color?: number[];
-        constantAttenuation?: number;
-        linearAttenuation?: number;
-        quadraticAttenuation?: number;
-    }
+    export interface IGLTFBuffer extends IGLTFChildRootProperty {
+        uri?: string;
+        byteLength: number;
 
-    export interface IGLTFSpotLight {
-        color?: number[];
-        constantAttenuation?: number;
-        fallOfAngle?: number;
-        fallOffExponent?: number;
-        linearAttenuation?: number;
-        quadraticAttenuation?: number;
+        // Loaded buffer (optimize)
+        loadedBufferView: ArrayBufferView
     }
 
-    export interface IGLTFLight extends IGLTFChildRootProperty {
-        type: string;
+    export interface IGLTFBufferView extends IGLTFChildRootProperty {
+        buffer: number;
+        byteOffset: number;
+        byteLength: number;
+        target?: EBufferViewTarget;
     }
 
     export interface IGLTFCameraOrthographic {
@@ -264,55 +181,63 @@ module BABYLON {
     }
 
     export interface IGLTFCamera extends IGLTFChildRootProperty {
+        orthographic?: IGLTFCameraOrthographic;
+        perspective?: IGLTFCameraPerspective;
         type: string;
     }
 
-    export interface IGLTFAnimationChannelTarget {
-        id: string;
-        path: string;
+    export interface IGLTFImage extends IGLTFChildRootProperty {
+        uri?: string;
+        mimeType?: string;
+        bufferView?: number;
     }
 
-    export interface IGLTFAnimationChannel {
-        sampler: string;
-        target: IGLTFAnimationChannelTarget;
+    export interface IGLTFMaterialNormalTextureInfo extends IGLTFTextureInfo {
+        scale: number;
     }
 
-    export interface IGLTFAnimationSampler {
-        input: string;
-        output: string;
-
-        interpolation?: string;
+    export interface IGLTFMaterialOcclusionTextureInfo extends IGLTFTextureInfo {
+        strength: number;
     }
 
-    export interface IGLTFAnimation extends IGLTFChildRootProperty {
-        channels?: IGLTFAnimationChannel[];
-        parameters?: Object;
-        samplers?: Object;
+    export interface IGLTFMaterialPbrMetallicRoughness {
+        baseColorFactor: number[];
+        baseColorTexture: IGLTFTextureInfo;
+        metallicFactor: number;
+        roughnessFactor: number;
+        metallicRoughnessTexture: IGLTFTextureInfo;
     }
 
-    export interface IGLTFNodeInstanceSkin {
-        skeletons: string[];
-        skin: string;
-        meshes: string[];
+    export interface IGLTFMaterial extends IGLTFChildRootProperty {
+        pbrMetallicRoughness?: IGLTFMaterialPbrMetallicRoughness;
+        normalTexture?: IGLTFMaterialNormalTextureInfo;
+        occlusionTexture?: IGLTFMaterialOcclusionTextureInfo;
+        emissiveTexture?: IGLTFTextureInfo;
+        emissiveFactor?: number[];
+
+        // Babylon.js values (optimize)
+        babylonMaterial?: PBRMaterial;
     }
 
-    export interface IGLTFSkins extends IGLTFChildRootProperty {
-        bindShapeMatrix: number[];
-        inverseBindMatrices: string;
-        jointNames: string[];
+    export interface IGLTFMeshPrimitive extends IGLTFProperty {
+        attributes: { [name: string]: number };
+        indices?: number;
+        material?: number;
+        mode?: EMeshPrimitiveMode;
+    }
 
-        babylonSkeleton?: Skeleton;
+    export interface IGLTFMesh extends IGLTFChildRootProperty {
+        primitives: IGLTFMeshPrimitive[];
     }
 
     export interface IGLTFNode extends IGLTFChildRootProperty {
-        camera?: string;
-        children: string[];
-        skin?: string;
-        jointName?: string;
-        light?: string;
+        camera?: number;
+        children?: number[];
+        skeletons?: number[];
+        skin?: number;
+        jointName?: number;
         matrix: number[];
-        mesh?: string;
-        meshes?: string[];
+        mesh?: number;
         rotation?: number[];
         scale?: number[];
         translation?: number[];
@@ -321,48 +246,68 @@ module BABYLON {
         babylonNode?: Node;
     }
 
+    export interface IGLTFSampler extends IGLTFChildRootProperty {
+        magFilter?: ETextureMagFilter;
+        minFilter?: ETextureMinFilter;
+        wrapS?: ETextureWrapMode;
+        wrapT?: ETextureWrapMode;
+    }
+
     export interface IGLTFScene extends IGLTFChildRootProperty {
-        nodes: string[];
+        nodes: number[];
     }
 
-    /**
-    * Runtime
-    */
-    export interface IGLTFRuntime {
-        extensions: Object;
-        accessors: Object;
-        buffers: Object;
-        bufferViews: Object;
-        meshes: Object;
-        lights: Object;
-        cameras: Object;
-        nodes: Object;
-        images: Object;
-        textures: Object;
-        shaders: Object;
-        programs: Object;
-        samplers: Object;
-        techniques: Object;
-        materials: Object;
-        animations: Object;
-        skins: Object;
-
-        currentScene?: Object;
-        scenes: Object; // v1.1
-
-        extensionsUsed: string[];
-        extensionsRequired?: string[]; // v1.1
-
-        buffersCount: number;
-        shaderscount: number;
-
-        scene: Scene;
-        rootUrl: string;
+    export interface IGLTFSkin extends IGLTFChildRootProperty {
+        bindShapeMatrix?: number[];
+        inverseBindMatrices?: number;
+        jointNames: number[];
 
-        loadedBufferCount: number;
-        loadedBufferViews: { [name: string]: ArrayBufferView };
+        babylonSkeleton?: Skeleton;
+    }
+
+    export interface IGLTFTexture extends IGLTFChildRootProperty {
+        format?: ETextureFormat;
+        internalFormat?: ETextureFormat;
+        sampler: number;
+        source: number;
+        target?: ETextureTarget;
+        type?: ETextureType;
 
-        loadedShaderCount: number;
+        // Babylon.js values (optimize)
+        babylonTexture?: Texture;
+    }
+
+    export interface IGLTFTextureInfo {
+        index: number;
+        texCoord?: number;
+    }
+
+    export interface IGLTF extends IGLTFProperty {
+        accessors?: IGLTFAccessor[];
+        animations?: IGLTFAnimation[];
+        asset: IGLTFAsset;
+        buffers?: IGLTFBuffer[];
+        bufferViews?: IGLTFBufferView[];
+        cameras?: IGLTFCamera[];
+        extensionsUsed?: string[];
+        extensionsRequired?: string[];
+        glExtensionsUsed?: string[];
+        images?: IGLTFImage[];
+        materials?: IGLTFMaterial[];
+        meshes?: IGLTFMesh[];
+        nodes?: IGLTFNode[];
+        samplers?: IGLTFSampler[];
+        scene?: number;
+        scenes?: IGLTFScene[];
+        skins?: IGLTFSkin[];
+        textures?: IGLTFTexture[];
+    }
+
+    export interface IGLTFRuntime {
+        gltf: IGLTF;
+
+        babylonScene: Scene;
+        rootUrl: string;
 
         importOnlyMeshes: boolean;
         importMeshesNames?: string[];

+ 22 - 131
loaders/src/glTF/babylon.glTFFileLoaderUtils.ts

@@ -6,82 +6,6 @@ module BABYLON {
     */
     export class GLTFUtils {
         /**
-         * Sets the given "parameter" matrix
-         * @param scene: the {BABYLON.Scene} object
-         * @param source: the source node where to pick the matrix
-         * @param parameter: the GLTF technique parameter
-         * @param uniformName: the name of the shader's uniform
-         * @param shaderMaterial: the shader material
-         */
-        public static SetMatrix(scene: Scene, source: Node, parameter: IGLTFTechniqueParameter, uniformName: string, shaderMaterial: ShaderMaterial | Effect): void {
-            var mat: Matrix = null;
-
-            if (parameter.semantic === "MODEL") {
-                mat = source.getWorldMatrix();
-            }
-            else if (parameter.semantic === "PROJECTION") {
-                mat = scene.getProjectionMatrix();
-            }
-            else if (parameter.semantic === "VIEW") {
-                mat = scene.getViewMatrix();
-            }
-            else if (parameter.semantic === "MODELVIEWINVERSETRANSPOSE") {
-                mat = Matrix.Transpose(source.getWorldMatrix().multiply(scene.getViewMatrix()).invert());
-            }
-            else if (parameter.semantic === "MODELVIEW") {
-                mat = source.getWorldMatrix().multiply(scene.getViewMatrix());
-            }
-            else if (parameter.semantic === "MODELVIEWPROJECTION") {
-                mat = source.getWorldMatrix().multiply(scene.getTransformMatrix());
-            }
-            else if (parameter.semantic === "MODELINVERSE") {
-                mat = source.getWorldMatrix().invert();
-            }
-            else if (parameter.semantic === "VIEWINVERSE") {
-                mat = scene.getViewMatrix().invert();
-            }
-            else if (parameter.semantic === "PROJECTIONINVERSE") {
-                mat = scene.getProjectionMatrix().invert();
-            }
-            else if (parameter.semantic === "MODELVIEWINVERSE") {
-                mat = source.getWorldMatrix().multiply(scene.getViewMatrix()).invert();
-            }
-            else if (parameter.semantic === "MODELVIEWPROJECTIONINVERSE") {
-                mat = source.getWorldMatrix().multiply(scene.getTransformMatrix()).invert();
-            }
-            else if (parameter.semantic === "MODELINVERSETRANSPOSE") {
-                mat = Matrix.Transpose(source.getWorldMatrix().invert());
-            }
-            else {
-                debugger;
-            }
-
-            switch (parameter.type) {
-                case EParameterType.FLOAT_MAT2: shaderMaterial.setMatrix2x2(uniformName, Matrix.GetAsMatrix2x2(mat)); break;
-                case EParameterType.FLOAT_MAT3: shaderMaterial.setMatrix3x3(uniformName, Matrix.GetAsMatrix3x3(mat)); break;
-                case EParameterType.FLOAT_MAT4: shaderMaterial.setMatrix(uniformName, mat); break;
-                default: break;
-            }
-        }
-
-        /**
-         * Sets the given "parameter" matrix
-         * @param shaderMaterial: the shader material
-         * @param uniform: the name of the shader's uniform
-         * @param value: the value of the uniform
-         * @param type: the uniform's type (EParameterType FLOAT, VEC2, VEC3 or VEC4)
-         */
-        public static SetUniform(shaderMaterial: ShaderMaterial | Effect, uniform: string, value: any, type: number): boolean {
-            switch (type) {
-                case EParameterType.FLOAT: shaderMaterial.setFloat(uniform, value); return true;
-                case EParameterType.FLOAT_VEC2: shaderMaterial.setVector2(uniform, Vector2.FromArray(value)); return true;
-                case EParameterType.FLOAT_VEC3: shaderMaterial.setVector3(uniform, Vector3.FromArray(value)); return true;
-                case EParameterType.FLOAT_VEC4: shaderMaterial.setVector4(uniform, Vector4.FromArray(value)); return true;
-                default: return false;
-            }
-        }
-
-        /**
         * If the uri is a base64 string
         * @param uri: the uri to test
         */
@@ -141,21 +65,21 @@ module BABYLON {
          * Returns the texture filter mode giving a mode value
          * @param mode: the filter mode value
          */
-        public static GetTextureFilterMode(mode: number): ETextureFilterType {
+        public static GetTextureFilterMode(mode: number): ETextureMinFilter {
             switch (mode) {
-                case ETextureFilterType.LINEAR:
-                case ETextureFilterType.LINEAR_MIPMAP_NEAREST:
-                case ETextureFilterType.LINEAR_MIPMAP_LINEAR: return Texture.TRILINEAR_SAMPLINGMODE;
-                case ETextureFilterType.NEAREST:
-                case ETextureFilterType.NEAREST_MIPMAP_NEAREST: return Texture.NEAREST_SAMPLINGMODE;
+                case ETextureMinFilter.LINEAR:
+                case ETextureMinFilter.LINEAR_MIPMAP_NEAREST:
+                case ETextureMinFilter.LINEAR_MIPMAP_LINEAR: return Texture.TRILINEAR_SAMPLINGMODE;
+                case ETextureMinFilter.NEAREST:
+                case ETextureMinFilter.NEAREST_MIPMAP_NEAREST: return Texture.NEAREST_SAMPLINGMODE;
                 default: return Texture.BILINEAR_SAMPLINGMODE;
             }
         }
 
-        public static GetBufferFromBufferView(gltfRuntime: IGLTFRuntime, bufferView: IGLTFBufferView, byteOffset: number, byteLength: number, componentType: EComponentType): ArrayBufferView {
+        public static GetBufferFromBufferView(runtime: IGLTFRuntime, bufferView: IGLTFBufferView, byteOffset: number, byteLength: number, componentType: EComponentType): ArrayBufferView {
             var byteOffset = bufferView.byteOffset + byteOffset;
 
-            var loadedBufferView = gltfRuntime.loadedBufferViews[bufferView.buffer];
+            var loadedBufferView = runtime.gltf.buffers[bufferView.buffer].loadedBufferView;
             if (byteOffset + byteLength > loadedBufferView.byteLength) {
                 throw new Error("Buffer access is out of range");
             }
@@ -174,13 +98,13 @@ module BABYLON {
 
         /**
          * Returns a buffer from its accessor
-         * @param gltfRuntime: the GLTF runtime
+         * @param runtime: the GLTF runtime
          * @param accessor: the GLTF accessor
          */
-        public static GetBufferFromAccessor(gltfRuntime: IGLTFRuntime, accessor: IGLTFAccessor): any {
-            var bufferView: IGLTFBufferView = gltfRuntime.bufferViews[accessor.bufferView];
+        public static GetBufferFromAccessor(runtime: IGLTFRuntime, accessor: IGLTFAccessor): any {
+            var bufferView = runtime.gltf.bufferViews[accessor.bufferView];
             var byteLength = accessor.count * GLTFUtils.GetByteStrideFromType(accessor);
-            return GLTFUtils.GetBufferFromBufferView(gltfRuntime, bufferView, accessor.byteOffset, byteLength, accessor.componentType);
+            return GLTFUtils.GetBufferFromBufferView(runtime, bufferView, accessor.byteOffset, byteLength, accessor.componentType);
         }
 
         /**
@@ -199,57 +123,24 @@ module BABYLON {
         }
 
         /**
-         * Returns the default material of gltf. Related to
-         * https://github.com/KhronosGroup/glTF/tree/master/specification/1.0#appendix-a-default-material
+         * Returns the default material of gltf.
          * @param scene: the Babylon.js scene
          */
-        public static GetDefaultMaterial(scene: Scene): ShaderMaterial {
+        public static GetDefaultMaterial(scene: Scene): PBRMaterial {
             if (!GLTFUtils._DefaultMaterial) {
-                Effect.ShadersStore["GLTFDefaultMaterialVertexShader"] = [
-                    "precision highp float;",
-                    "",
-                    "uniform mat4 worldView;",
-                    "uniform mat4 projection;",
-                    "",
-                    "attribute vec3 position;",
-                    "",
-                    "void main(void)",
-                    "{",
-                    "    gl_Position = projection * worldView * vec4(position, 1.0);",
-                    "}"
-                ].join("\n");
-
-                Effect.ShadersStore["GLTFDefaultMaterialPixelShader"] = [
-                    "precision highp float;",
-                    "",
-                    "uniform vec4 u_emission;",
-                    "",
-                    "void main(void)",
-                    "{",
-                    "    gl_FragColor = u_emission;",
-                    "}"
-                ].join("\n");
-
-                var shaderPath = {
-                    vertex: "GLTFDefaultMaterial",
-                    fragment: "GLTFDefaultMaterial"
-                };
-
-                var options = {
-                    attributes: ["position"],
-                    uniforms: ["worldView", "projection", "u_emission"],
-                    samplers: [],
-                    needAlphaBlending: false
-                };
-
-                GLTFUtils._DefaultMaterial = new ShaderMaterial("GLTFDefaultMaterial", scene, shaderPath, options);
-                GLTFUtils._DefaultMaterial.setColor4("u_emission", new Color4(0.5, 0.5, 0.5, 1.0));
+                var material = new PBRMaterial("gltf_default", scene);
+                material.sideOrientation = Material.CounterClockWiseSideOrientation;
+                material.albedoColor = new Color3(0.5, 0.5, 0.5);
+                material.metallic = 0;
+                material.roughness = 0.5;
+
+                GLTFUtils._DefaultMaterial = material;
             }
 
             return GLTFUtils._DefaultMaterial;
         }
 
         // The GLTF default material
-        private static _DefaultMaterial: ShaderMaterial = null;
+        private static _DefaultMaterial: PBRMaterial = null;
     }
 }

+ 30 - 28
loaders/src/glTF/babylon.glTFMaterialCommonExtension.ts

@@ -1,7 +1,7 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON {
-    interface IGLTFMaterialCommonExtensionValues {
+    interface IGLTFMaterialsCommonExtensionValues {
         ambient?: number[] | string;
         diffuse?: number[] | string;
         emission?: number[] | string;
@@ -10,11 +10,11 @@ module BABYLON {
         transparency?: number;
     };
 
-    interface IGLTFMaterialCommonExtension {
+    interface IGLTFMaterialsCommonExtension {
         technique: string;
         transparent?: number;
         doubleSided?: boolean;
-        values: IGLTFMaterialCommonExtensionValues;
+        values: IGLTFMaterialsCommonExtensionValues;
     };
 
     interface IGLTFRuntimeCommonExtension {
@@ -55,17 +55,17 @@ module BABYLON {
         quadraticAttenuation: number;
     }
 
-    export class GLTFMaterialCommonExtension extends GLTFFileLoaderExtension {
+    export class GLTFMaterialsCommonExtension extends GLTFFileLoaderExtension {
 
         constructor() {
             super("KHR_materials_common");
         }
 
-        public loadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError: () => void): boolean {
-            if (!gltfRuntime.extensions) return false;
+        protected postCreateRuntime(runtime: IGLTFRuntime): void {
+            if (!runtime.gltf.extensions) return;
 
-            var extension = gltfRuntime.extensions[this.name];
-            if (!extension) return false;
+            var extension = runtime.gltf.extensions[this.name];
+            if (!extension) return;
 
             // Create lights
             var lights: IGLTFRuntimeCommonExtension = extension.lights;
@@ -75,17 +75,17 @@ module BABYLON {
 
                     switch (light.type) {
                         case "ambient":
-                            var ambientLight = new HemisphericLight(light.name, new Vector3(0, 1, 0), gltfRuntime.scene);
+                            var ambientLight = new HemisphericLight(light.name, new Vector3(0, 1, 0), runtime.babylonScene);
                             var ambient = light.ambient;
                             ambientLight.diffuse = Color3.FromArray(ambient.color || [1, 1, 1]);
                             break;
                         case "point":
-                            var pointLight = new PointLight(light.name, new Vector3(10, 10, 10), gltfRuntime.scene);
+                            var pointLight = new PointLight(light.name, new Vector3(10, 10, 10), runtime.babylonScene);
                             var point = light.point;
                             pointLight.diffuse = Color3.FromArray(point.color || [1, 1, 1]);
                             break;
                         case "directional":
-                            var dirLight = new DirectionalLight(light.name, new Vector3(0, -1, 0), gltfRuntime.scene);
+                            var dirLight = new DirectionalLight(light.name, new Vector3(0, -1, 0), runtime.babylonScene);
                             var directional = light.directional;
                             dirLight.diffuse = Color3.FromArray(directional.color || [1, 1, 1]);
                             break;
@@ -94,25 +94,23 @@ module BABYLON {
                             var spotLight = new SpotLight(light.name, new Vector3(0, 10, 0), new Vector3(0, -1, 0),
                                                           light.spot.fallOffAngle || Math.PI,
                                                           light.spot.fallOffExponent || 0.0,
-                                                          gltfRuntime.scene);
+                                                          runtime.babylonScene);
                             spotLight.diffuse = Color3.FromArray(spot.color || [1, 1, 1]);
                             break;
-                        default: Tools.Warn("GLTF Material Common extension: light type \"" + light.type + "\” not supported"); break;
+                        default: Tools.Warn("GLTF Materials Common extension: light type \"" + light.type + "\” not supported"); break;
                     }
                 }
             }
-
-            return false;
         }
 
-        public loadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): boolean {
-            var material: IGLTFMaterial = gltfRuntime.materials[id];
+        protected loadMaterial(runtime: IGLTFRuntime, index: number): boolean {
+            var material = runtime.gltf.materials[index];
             if (!material || !material.extensions) return false;
 
-            var extension: IGLTFMaterialCommonExtension = material.extensions[this.name];
+            var extension: IGLTFMaterialsCommonExtension = material.extensions[this.name];
             if (!extension) return false;
 
-            var standardMaterial = new StandardMaterial(id, gltfRuntime.scene);
+            var standardMaterial = new StandardMaterial(material.name || "mat" + index, runtime.babylonScene);
             standardMaterial.sideOrientation = Material.CounterClockWiseSideOrientation;
 
             if (extension.technique === "CONSTANT") {
@@ -122,10 +120,11 @@ module BABYLON {
             standardMaterial.backFaceCulling = extension.doubleSided === undefined ? false : !extension.doubleSided;
             standardMaterial.alpha = extension.values.transparency === undefined ? 1.0 : extension.values.transparency;
             standardMaterial.specularPower = extension.values.shininess === undefined ? 0.0 : extension.values.shininess;
-            
+
+            /*
             // Ambient
             if (typeof extension.values.ambient === "string") {
-                this._loadTexture(gltfRuntime, extension.values.ambient, standardMaterial, "ambientTexture", onError);
+                this._loadTexture(runtime, extension.values.ambient, standardMaterial, "ambientTexture", onError);
             }
             else {
                 standardMaterial.ambientColor = Color3.FromArray(extension.values.ambient || [0, 0, 0]);
@@ -133,7 +132,7 @@ module BABYLON {
 
             // Diffuse
             if (typeof extension.values.diffuse === "string") {
-                this._loadTexture(gltfRuntime, extension.values.diffuse, standardMaterial, "diffuseTexture", onError);
+                this._loadTexture(runtime, extension.values.diffuse, standardMaterial, "diffuseTexture", onError);
             }
             else {
                 standardMaterial.diffuseColor = Color3.FromArray(extension.values.diffuse || [0, 0, 0]);
@@ -141,7 +140,7 @@ module BABYLON {
 
             // Emission
             if (typeof extension.values.emission === "string") {
-                this._loadTexture(gltfRuntime, extension.values.emission, standardMaterial, "emissiveTexture", onError);
+                this._loadTexture(runtime, extension.values.emission, standardMaterial, "emissiveTexture", onError);
             }
             else {
                 standardMaterial.emissiveColor = Color3.FromArray(extension.values.emission || [0, 0, 0]);
@@ -149,23 +148,26 @@ module BABYLON {
 
             // Specular
             if (typeof extension.values.specular === "string") {
-                this._loadTexture(gltfRuntime, extension.values.specular, standardMaterial, "specularTexture", onError);
+                this._loadTexture(runtime, extension.values.specular, standardMaterial, "specularTexture", onError);
             }
             else {
                 standardMaterial.specularColor = Color3.FromArray(extension.values.specular || [0, 0, 0]);
             }
+            */
 
             return true;
         }
 
-        private _loadTexture(gltfRuntime: IGLTFRuntime, id: string, material: StandardMaterial, propertyPath: string, onError: () => void): void {
+        /*
+        private _loadTexture(runtime: IGLTFRuntime, id: string, material: StandardMaterial, propertyPath: string, onError: () => void): void {
             // Create buffer from texture url
-            GLTFFileLoaderBase.LoadTextureBufferAsync(gltfRuntime, id, (buffer) => {
+            GLTFFileLoaderBase.LoadTextureBufferAsync(runtime, id, (buffer) => {
                 // Create texture from buffer
-                GLTFFileLoaderBase.CreateTextureAsync(gltfRuntime, id, buffer, (texture) => material[propertyPath] = texture, onError);
+                GLTFFileLoaderBase.CreateTextureAsync(runtime, id, buffer, (texture) => material[propertyPath] = texture, onError);
             }, onError);
         }
+        */
     }
 
-    GLTFFileLoader.RegisterExtension(new GLTFMaterialCommonExtension());
+    GLTFFileLoader.RegisterExtension(new GLTFMaterialsCommonExtension());
 }

+ 55 - 0
loaders/src/glTF/babylon.glTFMaterialsPbrSpecularGlossinessExtension.ts

@@ -0,0 +1,55 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON {
+    interface IGLTFMaterialsPbrSpecularGlossiness {
+        diffuseFactor: number[];
+        diffuseTexture: IGLTFTextureInfo;
+        specularFactor: number[];
+        glossinessFactor: number;
+        specularGlossinessTexture: IGLTFTextureInfo;
+    }
+
+    export class GLTFMaterialsPbrSpecularGlossinessExtension extends GLTFFileLoaderExtension {
+        constructor() {
+            super("KHR_materials_pbrSpecularGlossiness");
+        }
+
+        protected loadMaterial(runtime: IGLTFRuntime, index: number): boolean {
+            var material = GLTFFileLoader.LoadMaterial(runtime, index);
+            if (!material || !material.extensions) return false;
+
+            var properties: IGLTFMaterialsPbrSpecularGlossiness = material.extensions[this.name];
+            if (!properties) return false;
+
+            material.babylonMaterial.albedoColor = properties.diffuseFactor ? Color3.FromArray(properties.diffuseFactor) : new Color3(1, 1, 1);
+            material.babylonMaterial.reflectivityColor = properties.specularFactor ? Color3.FromArray(properties.specularFactor) : new Color3(1, 1, 1);
+            material.babylonMaterial.microSurface = properties.glossinessFactor === undefined ? 1 : properties.glossinessFactor;
+
+            if (properties.diffuseTexture) {
+                GLTFFileLoader.LoadTextureAsync(runtime, properties.diffuseTexture,
+                    texture => {
+                        material.babylonMaterial.albedoTexture = texture;
+                    },
+                    () => {
+                        Tools.Warn("Failed to load diffuse texture");
+                    });
+            }
+
+            if (properties.specularGlossinessTexture) {
+                GLTFFileLoader.LoadTextureAsync(runtime, properties.specularGlossinessTexture,
+                    texture => {
+                        material.babylonMaterial.reflectivityTexture = texture;
+                        material.babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
+                    },
+                    () => {
+                        Tools.Warn("Failed to load metallic roughness texture");
+                    });
+            }
+
+            GLTFFileLoader.LoadCommonMaterialProperties(runtime, material);
+            return true;
+        }
+    }
+
+    GLTFFileLoader.RegisterExtension(new GLTFMaterialsPbrSpecularGlossinessExtension());
+}

+ 8 - 5
loaders/src/tsconfig.json

@@ -1,7 +1,10 @@
 {
-    "compilerOptions": {
-        "experimentalDecorators": true,
-        "module": "commonjs", 
-        "target": "es5"
-    }
+  "compileOnSave": true,
+  "compilerOptions": {
+    "experimentalDecorators": true,
+    "module": "commonjs",
+    "target": "es5",
+    "sourceMap": true,
+    "lib": ["dom", "es2015.promise", "es5"]
+  }
 }