瀏覽代碼

merged with master

Benjamin Guignabert 8 年之前
父節點
當前提交
673cf8ffca
共有 57 個文件被更改,包括 10104 次插入10275 次删除
  1. 1 0
      Playground/frame.js
  2. 3 1
      Playground/index.js
  3. 22 6
      Tools/Gulp/config.json
  4. 19 19
      Tools/Gulp/profiling.html
  5. 27 27
      dist/preview release/babylon.core.js
  6. 2649 2631
      dist/preview release/babylon.d.ts
  7. 37 37
      dist/preview release/babylon.js
  8. 291 104
      dist/preview release/babylon.max.js
  9. 2649 2631
      dist/preview release/babylon.module.d.ts
  10. 37 37
      dist/preview release/babylon.noworker.js
  11. 11 11
      dist/preview release/canvas2D/babylon.canvas2d.min.js
  12. 251 251
      dist/preview release/inspector/babylon.inspector.bundle.js
  13. 3 3
      dist/preview release/inspector/babylon.inspector.min.js
  14. 19 504
      dist/preview release/loaders/babylon.glTFFileLoader.d.ts
  15. 163 2141
      dist/preview release/loaders/babylon.glTFFileLoader.js
  16. 1 2
      dist/preview release/loaders/babylon.glTFFileLoader.min.js
  17. 1 1
      dist/preview release/loaders/babylon.objFileLoader.min.js
  18. 1 1
      dist/preview release/materialsLibrary/babylon.waterMaterial.min.js
  19. 1 1
      dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js
  20. 1 1
      dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js
  21. 2 0
      dist/preview release/what's new.md
  22. 11 74
      loaders/src/glTF/babylon.glTFBinaryExtension.ts
  23. 1735 0
      loaders/src/glTF/1.0/babylon.glTFLoader.ts
  24. 23 23
      loaders/src/glTF/babylon.glTFFileLoaderExtension.ts
  25. 2 2
      loaders/src/glTF/babylon.glTFFileLoaderInterfaces.ts
  26. 2 2
      loaders/src/glTF/babylon.glTFFileLoaderUtils.ts
  27. 10 10
      loaders/src/glTF/babylon.glTFMaterialCommonExtension.ts
  28. 1200 0
      loaders/src/glTF/2.0/babylon.glTFLoader.ts
  29. 46 0
      loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts
  30. 350 0
      loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts
  31. 141 0
      loaders/src/glTF/2.0/babylon.glTFLoaderUtils.ts
  32. 56 0
      loaders/src/glTF/2.0/babylon.glTFMaterialsPbrSpecularGlossinessExtension.ts
  33. 25 14
      loaders/src/glTF/README.md
  34. 181 1664
      loaders/src/glTF/babylon.glTFFileLoader.ts
  35. 8 5
      loaders/src/tsconfig.json
  36. 5 5
      localDev/src/index.js
  37. 0 2
      src/Layer/babylon.highlightlayer.ts
  38. 0 2
      src/Layer/babylon.layer.ts
  39. 0 1
      src/LensFlare/babylon.lensFlareSystem.ts
  40. 0 1
      src/Lights/Shadows/babylon.shadowGenerator.ts
  41. 0 1
      src/Materials/Textures/Procedurals/babylon.proceduralTexture.ts
  42. 45 15
      src/Materials/babylon.effect.ts
  43. 9 0
      src/Materials/babylon.material.ts
  44. 3 3
      src/Materials/babylon.materialHelper.ts
  45. 11 4
      src/Materials/babylon.pbrMaterial.ts
  46. 10 6
      src/Materials/babylon.shaderMaterial.ts
  47. 12 6
      src/Materials/babylon.standardMaterial.ts
  48. 2 2
      src/Mesh/babylon.geometry.ts
  49. 12 2
      src/Mesh/babylon.subMesh.ts
  50. 0 1
      src/Particles/babylon.particleSystem.ts
  51. 0 1
      src/PostProcess/babylon.postProcess.ts
  52. 0 1
      src/PostProcess/babylon.volumetricLightScatteringPostProcess.ts
  53. 0 1
      src/Rendering/babylon.depthRenderer.ts
  54. 0 1
      src/Rendering/babylon.outlineRenderer.ts
  55. 7 4
      src/Shaders/pbr.fragment.fx
  56. 0 2
      src/Sprites/babylon.spriteManager.ts
  57. 9 11
      src/babylon.engine.ts

+ 1 - 0
Playground/frame.js

@@ -150,6 +150,7 @@
 
                 var hash = location.hash.substr(1);
                 currentSnippetToken = hash.split("#")[0];
+                if(!hash.split("#")[1]) hash += "#0";
 
                 xmlHttp.open("GET", snippetUrl + "/" + hash.replace("#", "/"));
                 xmlHttp.send();

+ 3 - 1
Playground/index.js

@@ -678,10 +678,12 @@
                                     }
                                 }
                             }
-                        }
+                        };
 
                         var hash = location.hash.substr(1);
                         currentSnippetToken = hash.split("#")[0];
+                        if(!hash.split("#")[1]) hash += "#0";
+
 
                         xmlHttp.open("GET", snippetUrl + "/" + hash.replace("#", "/"));
                         xmlHttp.send();

+ 22 - 6
Tools/Gulp/config.json

@@ -510,14 +510,30 @@
             },
             {
                 "files": [
-                    "../../loaders/src/glTF/babylon.glTFFileLoaderInterfaces.ts",
-                    "../../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.glTFFileLoader.ts"
                 ],
                 "output": "babylon.glTFFileLoader.js"
+            },
+            {
+                "files": [
+                    "../../loaders/src/glTF/1.0/babylon.glTFLoaderInterfaces.ts",
+                    "../../loaders/src/glTF/1.0/babylon.glTFLoader.ts",
+                    "../../loaders/src/glTF/1.0/babylon.glTFLoaderUtils.ts",
+                    "../../loaders/src/glTF/1.0/babylon.glTFLoaderExtension.ts",
+                    "../../loaders/src/glTF/1.0/babylon.glTFBinaryExtension.ts",
+                    "../../loaders/src/glTF/1.0/babylon.glTFMaterialsCommonExtension.ts"
+                ],
+                "output": "babylon.glTF1Loader.js"
+            },
+            {
+                "files": [
+                    "../../loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts",
+                    "../../loaders/src/glTF/2.0/babylon.glTFLoader.ts",
+                    "../../loaders/src/glTF/2.0/babylon.glTFLoaderUtils.ts",
+                    "../../loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts",
+                    "../../loaders/src/glTF/2.0/babylon.glTFMaterialsPbrSpecularGlossinessExtension.ts"
+                ],
+                "output": "babylon.glTF2Loader.js"
             }
         ],
         "build": {

+ 19 - 19
Tools/Gulp/profiling.html

@@ -3,26 +3,29 @@
     <title>Customize BJS for a specific Scene</title>
     <meta charset="UTF-8">
     <script src="../../dist/preview release/babylon.js"></script>
+    <style>
+    input.path {width:600px;}
+    input.filename {width:200px;}
+    em {color:red;}
+    </style>
     
 </head>
 <body onload="readConfigFile()">
 Obtain a FireFox performance file by:
 <ol>
 	<li>Make sure scene uses Babylon MAX.</li>
-	<li>Load the scene.</li>
-	<li>Turn on performance profiling.</li>
-	<li>Reload the scene (very important if code like sceneLoader runs on page load).</li>
+	<li>Add the temporary Javascript line <em>window.alert('Turn on Performance Recording')</em> just prior to Engine Instancing line.
+	<li>Load the scene, turn on performance profiling, &amp; click ok to the temporary alert.</li>
 	<li>Do anything that might call code in babylon.js not yet encountered.</li>
 	<li>Stop recording, and save the data as a file.</li>
 </ol>
 On this page:
 <ol>
 	<li>Select File with 'Browse' button below, and pick the file saved from above.</li>
-	<li>Make any changes of name to babylon file names.</li>
-	<li>Click Generate.</li>
+	<li>Make any changes of name to babylon file names &amp; directory..</li>
+	<li>Click Generate. Tip: change Firefox Option for Downloads to <em>Always ask me where to save files</em> to avoid having to move custom config to Gulp Directory.</li>
 	<li>Copy the 'custom.cofig.json' file generated in Downloads directory to the Gulp directory.</li>
-	<li>run: 'Gulp build-custom'</li>
-	<li>Copy generated scripts from dist/preview lease to where needed, and test.  Tip: test with the max version</li>
+	<li>Run: 'Gulp build-custom' then test with scene.  Tip: test with the max version generated.</li>
 	<li>If need stuff did not get recorded in performance file, then select file(s) &amp; click Generate again.</li>
 </ol>
 	<form>
@@ -32,11 +35,12 @@ On this page:
 		
 		<label>Profiling file: <input type="file" id="upload_file" name="upload" accept="text/*" multiple="" onchange="assignProfile(this.files[0])"/></label><br><br>
 		
-		Filename: <input type="text" id="filename" maxlength="32" value="babylon.custom.max.js">         
-		minFilename: <input type="text" id="minFilename" maxlength="32" value="babylon.custom.js"><br>         
+		Output Directory: <input class="path"     type="text" id="directory"   maxlength="256" value="C:/"> (clear for default of <em>../../dist/preview release</em>)<br>
+		Filename:         <input class="filename" type="text" id="filename"    maxlength="32"  value="babylon.custom.max.js">         
+		minFilename:      <input class="filename" type="text" id="minFilename" maxlength="32"  value="babylon.custom.js"><br>         
         Files Not In Recording: (Select those to still keep)
-			<input type="button" value="Generate" onclick="generate()"><br>
-        <select id="discards" multiple size="30">
+			<input type="button" value="Generate Custom Config" onclick="generate()"><br>
+        <select id="discards" multiple size="50">
         </select>
 
 	</form>
@@ -80,17 +84,10 @@ On this page:
 						// force stuff to always be added
 						appendSecondarySearches("decorators.js", "engine"); //needed for Serialize
 						appendSecondarySearches("stringDictionary.js", "engine"); //needed in Engine Constructor
-						appendSecondarySearches("loadingScreen.js", "engine"); //needed in Engine Constructor		
 						appendSecondarySearches("postProcessRenderPipelineManager.js", "scene"); //needed in Scene Constructor		
 						appendSecondarySearches("boundingBoxRenderer.js", "scene"); //needed in Scene Constructor		
 						appendSecondarySearches("collisionCoordinator.js", "scene"); //needed in Scene Constructor, from a called set of this.workerCollisions = false;
 						appendSecondarySearches("collider.js", "abstractMesh"); // needed in abstractMesh constructor
-						appendSecondarySearches("linesMesh.js", "geometry"); // needed in geometry constructor
-						appendSecondarySearches("multiMaterial.js", "subMesh"); // needed in subMesh.getMaterial()
-						appendSecondarySearches("pointLight.js", "subMesh"); // needed in MaterialHelper.PrepareDefinesForLights
-						appendSecondarySearches("spotLight.js", "subMesh"); // needed in MaterialHelper.PrepareDefinesForLights
-						appendSecondarySearches("hemisphericLight.js", "subMesh"); // needed in MaterialHelper.PrepareDefinesForLights
-						appendSecondarySearches("directionalLight.js", "subMesh"); // needed in MaterialHelper.PrepareDefinesForLights
 						appendSecondarySearches("videoTexture.js", "engine"); //needed in Engine._setTexture()	
 						
 						// there should always some detection of FreeCamera or ArcRotateCamera, but maybe not all inputs got recorded
@@ -191,14 +188,17 @@ On this page:
                 }
 			}
 
+			var directory   = document.getElementById("directory"  ).value;
 			var filename    = document.getElementById("filename"   ).value;
 			var minFilename = document.getElementById("minFilename").value;
+			
+			if (directory.length === 0) directory = "../../dist/preview release";
 	    	var out = '';
 	    	out += '{\n';
 	    	out += '  "build": {\n';
 	    	out += '	    "filename": "' + filename + '",\n';
 	    	out += '	    "minFilename": "' + minFilename + '",\n';
-	    	out += '	    "outputDirectory": "../../dist/preview release",\n';
+	    	out += '	    "outputDirectory":  "' + directory + '",\n';
 	    	out += '	    "srcOutputDirectory": "../../src/"\n';
 	    	out += '	  },\n';
 	    	out += '	  "core": {\n';

文件差異過大導致無法顯示
+ 27 - 27
dist/preview release/babylon.core.js


文件差異過大導致無法顯示
+ 2649 - 2631
dist/preview release/babylon.d.ts


文件差異過大導致無法顯示
+ 37 - 37
dist/preview release/babylon.js


文件差異過大導致無法顯示
+ 291 - 104
dist/preview release/babylon.max.js


文件差異過大導致無法顯示
+ 2649 - 2631
dist/preview release/babylon.module.d.ts


文件差異過大導致無法顯示
+ 37 - 37
dist/preview release/babylon.noworker.js


文件差異過大導致無法顯示
+ 11 - 11
dist/preview release/canvas2D/babylon.canvas2d.min.js


文件差異過大導致無法顯示
+ 251 - 251
dist/preview release/inspector/babylon.inspector.bundle.js


文件差異過大導致無法顯示
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


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

@@ -1,513 +1,28 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts" />
 declare module BABYLON {
-    /**
-    * Enums
-    */
-    enum EComponentType {
-        BYTE = 5120,
-        UNSIGNED_BYTE = 5121,
-        SHORT = 5122,
-        UNSIGNED_SHORT = 5123,
-        FLOAT = 5126,
+    interface IGLTFLoaderData {
+        json: Object;
+        bin: ArrayBufferView;
     }
-    enum EShaderType {
-        FRAGMENT = 35632,
-        VERTEX = 35633,
+    interface IGLTFLoader {
+        importMeshAsync: (meshesNames: any, scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onerror?: () => void) => boolean;
+        loadAsync: (scene: Scene, data: IGLTFLoaderData, rootUrl: string, onsuccess: () => void, onerror: () => void) => boolean;
     }
-    enum EParameterType {
-        BYTE = 5120,
-        UNSIGNED_BYTE = 5121,
-        SHORT = 5122,
-        UNSIGNED_SHORT = 5123,
-        INT = 5124,
-        UNSIGNED_INT = 5125,
-        FLOAT = 5126,
-        FLOAT_VEC2 = 35664,
-        FLOAT_VEC3 = 35665,
-        FLOAT_VEC4 = 35666,
-        INT_VEC2 = 35667,
-        INT_VEC3 = 35668,
-        INT_VEC4 = 35669,
-        BOOL = 35670,
-        BOOL_VEC2 = 35671,
-        BOOL_VEC3 = 35672,
-        BOOL_VEC4 = 35673,
-        FLOAT_MAT2 = 35674,
-        FLOAT_MAT3 = 35675,
-        FLOAT_MAT4 = 35676,
-        SAMPLER_2D = 35678,
-    }
-    enum ETextureWrapMode {
-        CLAMP_TO_EDGE = 33071,
-        MIRRORED_REPEAT = 33648,
-        REPEAT = 10497,
-    }
-    enum ETextureFilterType {
-        NEAREST = 9728,
-        LINEAR = 9728,
-        NEAREST_MIPMAP_NEAREST = 9984,
-        LINEAR_MIPMAP_NEAREST = 9985,
-        NEAREST_MIPMAP_LINEAR = 9986,
-        LINEAR_MIPMAP_LINEAR = 9987,
-    }
-    enum ETextureFormat {
-        ALPHA = 6406,
-        RGB = 6407,
-        RGBA = 6408,
-        LUMINANCE = 6409,
-        LUMINANCE_ALPHA = 6410,
-    }
-    enum ECullingType {
-        FRONT = 1028,
-        BACK = 1029,
-        FRONT_AND_BACK = 1032,
-    }
-    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,
-    }
-    /**
-    * Interfaces
-    */
-    interface IGLTFProperty {
-        extensions?: Object;
-        extras?: Object;
-    }
-    interface IGLTFChildRootProperty extends IGLTFProperty {
-        name?: string;
-    }
-    interface IGLTFAccessor extends IGLTFChildRootProperty {
-        bufferView: string;
-        byteOffset: number;
-        byteStride: number;
-        count: number;
-        type: string;
-        componentType: EComponentType;
-        max?: number[];
-        min?: number[];
-        name?: string;
-    }
-    interface IGLTFBufferView extends IGLTFChildRootProperty {
-        buffer: string;
-        byteOffset: number;
-        byteLength: number;
-        target?: number;
-    }
-    interface IGLTFBuffer extends IGLTFChildRootProperty {
-        uri: string;
-        byteLength?: number;
-        type?: string;
-    }
-    interface IGLTFShader extends IGLTFChildRootProperty {
-        uri: string;
-        type: EShaderType;
-    }
-    interface IGLTFProgram extends IGLTFChildRootProperty {
-        attributes: string[];
-        fragmentShader: string;
-        vertexShader: string;
-    }
-    interface IGLTFTechniqueParameter {
-        type: number;
-        count?: number;
-        semantic?: string;
-        node?: string;
-        value?: number | boolean | string | Array<any>;
-        source?: string;
-        babylonValue?: any;
-    }
-    interface IGLTFTechniqueCommonProfile {
-        lightingModel: string;
-        texcoordBindings: Object;
-        parameters?: Array<any>;
-    }
-    interface IGLTFTechniqueStatesFunctions {
-        blendColor?: number[];
-        blendEquationSeparate?: number[];
-        blendFuncSeparate?: number[];
-        colorMask: boolean[];
-        cullFace: number[];
-    }
-    interface IGLTFTechniqueStates {
-        enable: number[];
-        functions: IGLTFTechniqueStatesFunctions;
-    }
-    interface IGLTFTechnique extends IGLTFChildRootProperty {
-        parameters: Object;
-        program: string;
-        attributes: Object;
-        uniforms: Object;
-        states: IGLTFTechniqueStates;
-    }
-    interface IGLTFMaterial extends IGLTFChildRootProperty {
-        technique?: string;
-        values: string[];
-    }
-    interface IGLTFMeshPrimitive extends IGLTFProperty {
-        attributes: Object;
-        indices: string;
-        material: string;
-        mode?: number;
-    }
-    interface IGLTFMesh extends IGLTFChildRootProperty {
-        primitives: IGLTFMeshPrimitive[];
-    }
-    interface IGLTFImage extends IGLTFChildRootProperty {
-        uri: string;
-    }
-    interface IGLTFSampler extends IGLTFChildRootProperty {
-        magFilter?: number;
-        minFilter?: number;
-        wrapS?: number;
-        wrapT?: number;
-    }
-    interface IGLTFTexture extends IGLTFChildRootProperty {
-        sampler: string;
-        source: string;
-        format?: ETextureFormat;
-        internalFormat?: ETextureFormat;
-        target?: number;
-        type?: number;
-        babylonTexture?: Texture;
-    }
-    interface IGLTFAmbienLight {
-        color?: number[];
-    }
-    interface IGLTFDirectionalLight {
-        color?: number[];
-    }
-    interface IGLTFPointLight {
-        color?: number[];
-        constantAttenuation?: number;
-        linearAttenuation?: number;
-        quadraticAttenuation?: number;
-    }
-    interface IGLTFSpotLight {
-        color?: number[];
-        constantAttenuation?: number;
-        fallOfAngle?: number;
-        fallOffExponent?: number;
-        linearAttenuation?: number;
-        quadraticAttenuation?: number;
-    }
-    interface IGLTFLight extends IGLTFChildRootProperty {
-        type: string;
-    }
-    interface IGLTFCameraOrthographic {
-        xmag: number;
-        ymag: number;
-        zfar: number;
-        znear: number;
-    }
-    interface IGLTFCameraPerspective {
-        aspectRatio: number;
-        yfov: number;
-        zfar: number;
-        znear: number;
-    }
-    interface IGLTFCamera extends IGLTFChildRootProperty {
-        type: string;
-    }
-    interface IGLTFAnimationChannelTarget {
-        id: string;
-        path: string;
-    }
-    interface IGLTFAnimationChannel {
-        sampler: string;
-        target: IGLTFAnimationChannelTarget;
-    }
-    interface IGLTFAnimationSampler {
-        input: string;
-        output: string;
-        interpolation?: string;
-    }
-    interface IGLTFAnimation extends IGLTFChildRootProperty {
-        channels?: IGLTFAnimationChannel[];
-        parameters?: Object;
-        samplers?: Object;
-    }
-    interface IGLTFNodeInstanceSkin {
-        skeletons: string[];
-        skin: string;
-        meshes: string[];
-    }
-    interface IGLTFSkins extends IGLTFChildRootProperty {
-        bindShapeMatrix: number[];
-        inverseBindMatrices: string;
-        jointNames: string[];
-        babylonSkeleton?: Skeleton;
-    }
-    interface IGLTFNode extends IGLTFChildRootProperty {
-        camera?: string;
-        children: string[];
-        skin?: string;
-        jointName?: string;
-        light?: string;
-        matrix: number[];
-        mesh?: string;
-        meshes?: string[];
-        rotation?: number[];
-        scale?: number[];
-        translation?: number[];
-        babylonNode?: Node;
-    }
-    interface IGLTFScene extends IGLTFChildRootProperty {
-        nodes: string[];
-    }
-    /**
-    * Runtime
-    */
-    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;
-        extensionsUsed: string[];
-        extensionsRequired?: string[];
-        buffersCount: number;
-        shaderscount: number;
-        scene: Scene;
-        rootUrl: string;
-        loadedBufferCount: number;
-        loadedBufferViews: {
-            [name: string]: ArrayBufferView;
-        };
-        loadedShaderCount: number;
-        importOnlyMeshes: boolean;
-        importMeshesNames?: string[];
-        dummyNodes: Node[];
-    }
-    /**
-    * Bones
-    */
-    interface INodeToRoot {
-        bone: Bone;
-        node: IGLTFNode;
-        id: string;
-    }
-    interface IJointNode {
-        node: IGLTFNode;
-        id: string;
-    }
-}
-
-/// <reference path="../../../dist/preview release/babylon.d.ts" />
-declare module BABYLON {
-    /**
-    * Implementation of the base glTF spec
-    */
-    class GLTFFileLoaderBase {
-        static CreateRuntime(parsedData: any, scene: Scene, rootUrl: string): IGLTFRuntime;
-        static LoadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void, onProgress?: () => void): void;
-        static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): void;
-        static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: () => void): void;
-        static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: () => void): void;
-        static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): void;
-    }
-    /**
-    * glTF File Loader Plugin
-    */
     class GLTFFileLoader implements ISceneLoaderPluginAsync {
-        /**
-        * Public members
-        */
-        extensions: ISceneLoaderPluginExtensions;
-        /**
-        * Private members
-        */
-        /**
-        * Static members
-        */
+        static GLTFLoaderV1: IGLTFLoader;
+        static GLTFLoaderV2: IGLTFLoader;
         static HomogeneousCoordinates: boolean;
         static IncrementalLoading: boolean;
-        static Extensions: {
-            [name: string]: GLTFFileLoaderExtension;
-        };
-        static RegisterExtension(extension: GLTFFileLoaderExtension): void;
-        /**
-        * Import meshes
-        */
-        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onSuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError?: () => void, onProgress?: () => void): boolean;
-        /**
-        * Load scene
-        */
-        loadAsync(scene: Scene, data: string, rootUrl: string, onSuccess: () => void, onError: () => void): boolean;
-        private _loadShadersAsync(gltfRuntime, onload);
-        private _loadBuffersAsync(gltfRuntime, onload, onProgress?);
-        private _createNodes(gltfRuntime);
-    }
-}
-
-/// <reference path="../../../dist/preview release/babylon.d.ts" />
-declare module BABYLON {
-    /**
-    * Utils functions for GLTF
-    */
-    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
-         */
-        static SetMatrix(scene: Scene, source: Node, parameter: IGLTFTechniqueParameter, uniformName: string, shaderMaterial: ShaderMaterial | Effect): void;
-        /**
-         * 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)
-         */
-        static SetUniform(shaderMaterial: ShaderMaterial | Effect, uniform: string, value: any, type: number): boolean;
-        /**
-        * If the uri is a base64 string
-        * @param uri: the uri to test
-        */
-        static IsBase64(uri: string): boolean;
-        /**
-        * Decode the base64 uri
-        * @param uri: the uri to decode
-        */
-        static DecodeBase64(uri: string): ArrayBuffer;
-        /**
-        * Returns the wrap mode of the texture
-        * @param mode: the mode value
-        */
-        static GetWrapMode(mode: number): number;
-        /**
-         * Returns the byte stride giving an accessor
-         * @param accessor: the GLTF accessor objet
-         */
-        static GetByteStrideFromType(accessor: IGLTFAccessor): number;
-        /**
-         * Returns the texture filter mode giving a mode value
-         * @param mode: the filter mode value
-         */
-        static GetTextureFilterMode(mode: number): ETextureFilterType;
-        static GetBufferFromBufferView(gltfRuntime: IGLTFRuntime, bufferView: IGLTFBufferView, byteOffset: number, byteLength: number, componentType: EComponentType): ArrayBufferView;
-        /**
-         * Returns a buffer from its accessor
-         * @param gltfRuntime: the GLTF runtime
-         * @param accessor: the GLTF accessor
-         */
-        static GetBufferFromAccessor(gltfRuntime: IGLTFRuntime, accessor: IGLTFAccessor): any;
-        /**
-         * Decodes a buffer view into a string
-         * @param view: the buffer view
-         */
-        static DecodeBufferToText(view: ArrayBufferView): string;
-        /**
-         * Returns the default material of gltf. Related to
-         * https://github.com/KhronosGroup/glTF/tree/master/specification/1.0#appendix-a-default-material
-         * @param scene: the Babylon.js scene
-         */
-        static GetDefaultMaterial(scene: Scene): ShaderMaterial;
-        private static _DefaultMaterial;
-    }
-}
-
-/// <reference path="../../../dist/preview release/babylon.d.ts" />
-declare module BABYLON {
-    abstract class GLTFFileLoaderExtension {
-        private _name;
-        constructor(name: string);
-        readonly name: string;
-        /**
-        * Defines an override for loading the runtime
-        * Return true to stop further extensions from loading the runtime
-        */
-        loadRuntimeAsync(scene: Scene, data: string, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): boolean;
-        /**
-         * Defines an onverride for creating gltf runtime
-         * Return true to stop further extensions from creating the runtime
-         */
-        loadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError: () => void): boolean;
-        /**
-        * Defines an override for loading buffers
-        * Return true to stop further extensions from loading this buffer
-        */
-        loadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void, onProgress?: () => void): boolean;
-        /**
-        * Defines an override for loading texture buffers
-        * Return true to stop further extensions from loading this texture data
-        */
-        loadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): boolean;
-        /**
-        * Defines an override for creating textures
-        * Return true to stop further extensions from loading this texture
-        */
-        createTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: () => void): boolean;
-        /**
-        * Defines an override for loading shader strings
-        * Return true to stop further extensions from loading this shader data
-        */
-        loadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: () => void): boolean;
-        /**
-        * Defines an override for loading materials
-        * Return true to stop further extensions from loading this material
-        */
-        loadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): boolean;
-        static LoadRuntimeAsync(scene: Scene, data: string, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): void;
-        static LoadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError: () => void): void;
-        static LoadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (bufferView: ArrayBufferView) => void, onError: () => void, onProgress?: () => void): void;
-        static LoadTextureAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (texture: Texture) => void, onError: () => void): void;
-        static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderData: string) => void, onError: () => void): void;
-        static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): void;
-        private static LoadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);
-        private static CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);
-        private static ApplyExtensions(func, defaultFunc);
-    }
-}
-
-/// <reference path="../../../dist/preview release/babylon.d.ts" />
-declare module BABYLON {
-    class GLTFBinaryExtension extends GLTFFileLoaderExtension {
-        private _binary;
-        constructor();
-        loadRuntimeAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): boolean;
-        loadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): boolean;
-        loadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): boolean;
-        loadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderString: string) => void, onError: () => void): boolean;
-        private _parseBinary(data);
-    }
-}
-
-/// <reference path="../../../dist/preview release/babylon.d.ts" />
-declare module BABYLON {
-    class GLTFMaterialCommonExtension extends GLTFFileLoaderExtension {
-        constructor();
-        loadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError: () => void): boolean;
-        loadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): boolean;
-        private _loadTexture(gltfRuntime, id, material, propertyPath, onError);
+        extensions: ISceneLoaderPluginExtensions;
+        importMeshAsync(meshesNames: any, scene: Scene, data: any, rootUrl: string, onSuccess?: (meshes: AbstractMesh[], particleSystems: ParticleSystem[], skeletons: Skeleton[]) => void, onError?: () => void): boolean;
+        loadAsync(scene: Scene, data: string | ArrayBuffer, rootUrl: string, onSuccess: () => void, onError: () => void): boolean;
+        private static _parse(data);
+        private _getLoader(loaderData);
+        private static _parseBinary(data);
+        private static _parseV1(binaryReader);
+        private static _parseV2(binaryReader);
+        private static _parseVersion(version);
+        private static _compareVersion(a, b);
+        private static _decodeBufferToText(view);
     }
 }

文件差異過大導致無法顯示
+ 163 - 2141
dist/preview release/loaders/babylon.glTFFileLoader.js


文件差異過大導致無法顯示
+ 1 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


文件差異過大導致無法顯示
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


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

@@ -47,6 +47,8 @@
 - New material: `ShadowOnlyMaterial` to display shadows on transparent surfaces ([deltakosh](https://github.com/deltakosh)) 
 - Added `VertexBuffer.TangentKind` to specify tangents in place of shader-calculated tangents ([dewadswo](https://github.com/dewadswo), [bghgary](https://github.com/bghgary))
 - Added `material.twoSidedLighting` to PBRMaterial and StandardMaterial to enable flipping normals when backfaceCulling is false ([BeardedGnome](https://github.com/BeardedGnome), [bghgary](https://github.com/bghgary))
+- Added a [HTML page](https://github.com/BabylonJS/Babylon.js/blob/master/Tools/Gulp/profiling.html) with embedded directions to improve the custom build process. ([jcpalmer](https://github.com/Palmer-JC))
+- Added glTF 2.0 loader with versioning support ([bghgary](https://github.com/bghgary), thanks to [BeardedGnome](https://github.com/BeardedGnome) for animation updates)
  
 ### Bug fixes
 - Fixed a bug with spotlight direction ([deltakosh](https://github.com/deltakosh)) 

+ 11 - 74
loaders/src/glTF/babylon.glTFBinaryExtension.ts

@@ -1,17 +1,12 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 
-module BABYLON {
+module BABYLON.GLTF1 {
     const BinaryExtensionBufferName = "binary_glTF";
 
     enum EContentFormat {
         JSON = 0
     };
 
-    interface IGLTFBinaryExtension {
-        content: Object;
-        body: Uint8Array;
-    };
-
     interface IGLTFBinaryExtensionShader {
         bufferView: string;
     };
@@ -23,35 +18,21 @@ module BABYLON {
         width: number;
     };
 
-    export class GLTFBinaryExtension extends GLTFFileLoaderExtension {
-        private _binary: IGLTFBinaryExtension;
+    export class GLTFBinaryExtension extends GLTFLoaderExtension {
+        private _bin : ArrayBufferView;
 
         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)) {
+        public loadRuntimeAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): boolean {
+            var extensionsUsed = (<any>data.json).extensionsUsed;
+            if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1) {
                 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);
-            });
-
+            this._bin = data.bin;
+            onSuccess(GLTFLoaderBase.CreateRuntime(data.json, scene, rootUrl));
             return true;
         }
 
@@ -64,7 +45,7 @@ module BABYLON {
                 return false;
             }
 
-            onSuccess(this._binary.body);
+            onSuccess(this._bin);
             return true;
         }
 
@@ -99,50 +80,6 @@ module BABYLON {
 
             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 {
@@ -173,5 +110,5 @@ module BABYLON {
         }
     }
 
-    GLTFFileLoader.RegisterExtension(new GLTFBinaryExtension());
+    GLTFLoader.RegisterExtension(new GLTFBinaryExtension());
 }

文件差異過大導致無法顯示
+ 1735 - 0
loaders/src/glTF/1.0/babylon.glTFLoader.ts


+ 23 - 23
loaders/src/glTF/babylon.glTFFileLoaderExtension.ts

@@ -1,7 +1,7 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 
-module BABYLON {
-    export abstract class GLTFFileLoaderExtension {
+module BABYLON.GLTF1 {
+    export abstract class GLTFLoaderExtension {
         private _name: string;
 
         public constructor(name: string) {
@@ -16,7 +16,7 @@ module BABYLON {
         * Defines an override for loading the runtime
         * Return true to stop further extensions from loading the runtime
         */
-        public loadRuntimeAsync(scene: Scene, data: string, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): boolean {
+        public loadRuntimeAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): boolean {
             return false;
         }
 
@@ -72,18 +72,18 @@ module BABYLON {
         // Utilities
         // ---------
 
-        public static LoadRuntimeAsync(scene: Scene, data: string, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
+        public static LoadRuntimeAsync(scene: Scene, data: IGLTFLoaderData, rootUrl: string, onSuccess: (gltfRuntime: IGLTFRuntime) => void, onError: () => void): void {
+            GLTFLoaderExtension.ApplyExtensions(loaderExtension => {
                 return loaderExtension.loadRuntimeAsync(scene, data, rootUrl, onSuccess, onError);
             }, () => {
                 setTimeout(() => {
-                    onSuccess(GLTFFileLoaderBase.CreateRuntime(JSON.parse(data), scene, rootUrl));
+                    onSuccess(GLTFLoaderBase.CreateRuntime(data.json, scene, rootUrl));
                 });
             });
         }
 
         public static LoadRuntimeExtensionsAsync(gltfRuntime: IGLTFRuntime, onSuccess: () => void, onError: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
+            GLTFLoaderExtension.ApplyExtensions(loaderExtension => {
                 return loaderExtension.loadRuntimeExtensionsAsync(gltfRuntime, onSuccess, onError);
             }, () => {
                 setTimeout(() => {
@@ -93,54 +93,54 @@ module BABYLON {
         }
 
         public static LoadBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (bufferView: ArrayBufferView) => void, onError: () => void, onProgress?: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
+            GLTFLoaderExtension.ApplyExtensions(loaderExtension => {
                 return loaderExtension.loadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress);
             }, () => {
-                GLTFFileLoaderBase.LoadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress);
+                GLTFLoaderBase.LoadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress);
             });
         }
 
         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),
+            GLTFLoaderExtension.LoadTextureBufferAsync(gltfRuntime, id,
+                buffer => GLTFLoaderExtension.CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError),
                 onError);
         }
 
         public static LoadShaderStringAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (shaderData: string) => void, onError: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
+            GLTFLoaderExtension.ApplyExtensions(loaderExtension => {
                 return loaderExtension.loadShaderStringAsync(gltfRuntime, id, onSuccess, onError);
             }, () => {
-                GLTFFileLoaderBase.LoadShaderStringAsync(gltfRuntime, id, onSuccess, onError);
+                GLTFLoaderBase.LoadShaderStringAsync(gltfRuntime, id, onSuccess, onError);
             });
         }
 
         public static LoadMaterialAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (material: Material) => void, onError: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
+            GLTFLoaderExtension.ApplyExtensions(loaderExtension => {
                 return loaderExtension.loadMaterialAsync(gltfRuntime, id, onSuccess, onError);
             }, () => {
-                GLTFFileLoaderBase.LoadMaterialAsync(gltfRuntime, id, onSuccess, onError);
+                GLTFLoaderBase.LoadMaterialAsync(gltfRuntime, id, onSuccess, onError);
             });
         }
 
         private static LoadTextureBufferAsync(gltfRuntime: IGLTFRuntime, id: string, onSuccess: (buffer: ArrayBufferView) => void, onError: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
+            GLTFLoaderExtension.ApplyExtensions(loaderExtension => {
                 return loaderExtension.loadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);
             }, () => {
-                GLTFFileLoaderBase.LoadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);
+                GLTFLoaderBase.LoadTextureBufferAsync(gltfRuntime, id, onSuccess, onError);
             });
         }
 
         private static CreateTextureAsync(gltfRuntime: IGLTFRuntime, id: string, buffer: ArrayBufferView, onSuccess: (texture: Texture) => void, onError: () => void): void {
-            GLTFFileLoaderExtension.ApplyExtensions(loaderExtension => {
+            GLTFLoaderExtension.ApplyExtensions(loaderExtension => {
                 return loaderExtension.createTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);
             }, () => {
-                GLTFFileLoaderBase.CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);
+                GLTFLoaderBase.CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError);
             });
         }
 
-        private static ApplyExtensions(func: (loaderExtension: GLTFFileLoaderExtension) => boolean, defaultFunc: () => void): void {
-            for (var extensionName in GLTFFileLoader.Extensions) {
-                var loaderExtension = GLTFFileLoader.Extensions[extensionName];
+        private static ApplyExtensions(func: (loaderExtension: GLTFLoaderExtension) => boolean, defaultFunc: () => void): void {
+            for (var extensionName in GLTFLoader.Extensions) {
+                var loaderExtension = GLTFLoader.Extensions[extensionName];
                 if (func(loaderExtension)) {
                     return;
                 }

+ 2 - 2
loaders/src/glTF/babylon.glTFFileLoaderInterfaces.ts

@@ -1,6 +1,6 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 
-module BABYLON {
+module BABYLON.GLTF1 {
     /**
     * Enums
     */

+ 2 - 2
loaders/src/glTF/babylon.glTFFileLoaderUtils.ts

@@ -1,6 +1,6 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 
-module BABYLON {
+module BABYLON.GLTF1 {
     /**
     * Utils functions for GLTF
     */

+ 10 - 10
loaders/src/glTF/babylon.glTFMaterialCommonExtension.ts

@@ -1,7 +1,7 @@
-/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
 
-module BABYLON {
-    interface IGLTFMaterialCommonExtensionValues {
+module BABYLON.GLTF1 {
+    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,7 +55,7 @@ module BABYLON {
         quadraticAttenuation: number;
     }
 
-    export class GLTFMaterialCommonExtension extends GLTFFileLoaderExtension {
+    export class GLTFMaterialsCommonExtension extends GLTFLoaderExtension {
 
         constructor() {
             super("KHR_materials_common");
@@ -109,7 +109,7 @@ module BABYLON {
             var material: IGLTFMaterial = gltfRuntime.materials[id];
             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);
@@ -160,12 +160,12 @@ module BABYLON {
 
         private _loadTexture(gltfRuntime: IGLTFRuntime, id: string, material: StandardMaterial, propertyPath: string, onError: () => void): void {
             // Create buffer from texture url
-            GLTFFileLoaderBase.LoadTextureBufferAsync(gltfRuntime, id, (buffer) => {
+            GLTFLoaderBase.LoadTextureBufferAsync(gltfRuntime, id, (buffer) => {
                 // Create texture from buffer
-                GLTFFileLoaderBase.CreateTextureAsync(gltfRuntime, id, buffer, (texture) => material[propertyPath] = texture, onError);
+                GLTFLoaderBase.CreateTextureAsync(gltfRuntime, id, buffer, (texture) => material[propertyPath] = texture, onError);
             }, onError);
         }
     }
 
-    GLTFFileLoader.RegisterExtension(new GLTFMaterialCommonExtension());
+    GLTFLoader.RegisterExtension(new GLTFMaterialsCommonExtension());
 }

文件差異過大導致無法顯示
+ 1200 - 0
loaders/src/glTF/2.0/babylon.glTFLoader.ts


+ 46 - 0
loaders/src/glTF/2.0/babylon.glTFLoaderExtension.ts

@@ -0,0 +1,46 @@
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GLTF2 {
+    export abstract class GLTFLoaderExtension {
+        private _name: string;
+
+        public constructor(name: string) {
+            this._name = name;
+        }
+
+        public get name(): string {
+            return this._name;
+        }
+
+        protected postCreateRuntime(runtime: IGLTFRuntime): void {}
+
+        // Return true to stop other extensions from loading materials.
+        protected loadMaterial(runtime: IGLTFRuntime, index: number): boolean { return false; }
+
+        // ---------
+        // Utilities
+        // ---------
+
+        public static PostCreateRuntime(runtime: IGLTFRuntime): void {
+            for (var extensionName in GLTFLoader.Extensions) {
+                var extension = GLTFLoader.Extensions[extensionName];
+                extension.postCreateRuntime(runtime);
+            }
+        }
+
+        public static LoadMaterial(runtime: IGLTFRuntime, index: number): void {
+            for (var extensionName in GLTFLoader.Extensions) {
+                var extension = GLTFLoader.Extensions[extensionName];
+                if (extension.loadMaterial(runtime, index)) {
+                    return;
+                }
+            }
+
+            var material = GLTFLoader.LoadMaterial(runtime, index);
+            if (material) {
+                GLTFLoader.LoadMetallicRoughnessMaterialProperties(runtime, material);
+                GLTFLoader.LoadCommonMaterialProperties(runtime, material);
+            }
+        }
+    }
+}

+ 350 - 0
loaders/src/glTF/2.0/babylon.glTFLoaderInterfaces.ts

@@ -0,0 +1,350 @@
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GLTF2 {
+    /**
+    * Enums
+    */
+    export enum EBufferViewTarget {
+        ARRAY_BUFFER = 34962,
+        ELEMENT_ARRAY_BUFFER = 34963
+    }
+
+    export enum EComponentType {
+        BYTE = 5120,
+        UNSIGNED_BYTE = 5121,
+        SHORT = 5122,
+        UNSIGNED_SHORT = 5123,
+        FLOAT = 5126
+    }
+
+    export enum EMeshPrimitiveMode {
+        POINTS = 0,
+        LINES = 1,
+        LINE_LOOP = 2,
+        LINE_STRIP = 3,
+        TRIANGLES = 4,
+        TRIANGLE_STRIP = 5,
+        TRIANGLE_FAN = 6
+    }
+
+    export enum EParameterType {
+        BYTE = 5120,
+        UNSIGNED_BYTE = 5121,
+        SHORT = 5122,
+        UNSIGNED_SHORT = 5123,
+        INT = 5124,
+        UNSIGNED_INT = 5125,
+        FLOAT = 5126,
+        FLOAT_VEC2 = 35664,
+        FLOAT_VEC3 = 35665,
+        FLOAT_VEC4 = 35666,
+        INT_VEC2 = 35667,
+        INT_VEC3 = 35668,
+        INT_VEC4 = 35669,
+        BOOL = 35670,
+        BOOL_VEC2 = 35671,
+        BOOL_VEC3 = 35672,
+        BOOL_VEC4 = 35673,
+        FLOAT_MAT2 = 35674,
+        FLOAT_MAT3 = 35675,
+        FLOAT_MAT4 = 35676,
+        SAMPLER_2D = 35678
+    }
+
+    export enum ETextureMagFilter {
+        NEAREST = 9728,
+        LINEAR = 9728,
+    }
+
+    export enum ETextureMinFilter {
+        NEAREST = 9728,
+        LINEAR = 9728,
+        NEAREST_MIPMAP_NEAREST = 9984,
+        LINEAR_MIPMAP_NEAREST = 9985,
+        NEAREST_MIPMAP_LINEAR = 9986,
+        LINEAR_MIPMAP_LINEAR = 9987
+    }
+
+    export enum ETextureFormat {
+        ALPHA = 6406,
+        RGB = 6407,
+        RGBA = 6408,
+        LUMINANCE = 6409,
+        LUMINANCE_ALPHA = 6410
+    }
+
+    export enum ETextureTarget {
+        TEXTURE_2D = 3553
+    }
+
+    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
+    }
+
+    /**
+    * Interfaces
+    */
+    export interface IGLTFProperty {
+        extensions?: Object;
+        extras?: any;
+    }
+
+    export interface IGLTFChildRootProperty extends IGLTFProperty {
+        name?: string;
+    }
+
+    export interface IGLTFAccessorSparseIndices extends IGLTFProperty {
+        bufferView: number;
+        byteOffset?: number;
+        componentType: EComponentType;
+    }
+
+    export interface IGLTFAccessorSparseValues extends IGLTFProperty {
+        bufferView: number;
+        byteOffset?: number;
+    }
+
+    export interface IGLTFAccessorSparse extends IGLTFProperty {
+        count: number;
+        indices: IGLTFAccessorSparseIndices;
+        values: IGLTFAccessorSparseValues;
+    }
+
+    export interface IGLTFAccessor extends IGLTFChildRootProperty {
+        bufferView?: number;
+        byteOffset?: number;
+        componentType: EComponentType;
+        normalized?: boolean;
+        count: number;
+        type: string;
+        max: number[];
+        min: number[];
+        sparse?: IGLTFAccessorSparse;
+    }
+
+    export interface IGLTFAnimationChannel extends IGLTFProperty {
+        sampler: number;
+        target: IGLTFAnimationChannelTarget;
+    }
+
+    export interface IGLTFAnimationChannelTarget extends IGLTFProperty {
+        node: number;
+        path: string;
+    }
+
+    export interface IGLTFAnimationSampler extends IGLTFProperty {
+        input: number;
+        interpolation?: string;
+        output: number;
+    }
+
+    export interface IGLTFAnimation extends IGLTFChildRootProperty {
+        channels: IGLTFAnimationChannel[];
+        samplers: IGLTFAnimationSampler[];
+    }
+
+    export interface IGLTFAssetProfile extends IGLTFProperty {
+        api?: string;
+        version?: string;
+    }
+
+    export interface IGLTFAsset extends IGLTFChildRootProperty {
+        copyright?: string;
+        generator?: string;
+        profile?: IGLTFAssetProfile;
+        version: string;
+    }
+
+    export interface IGLTFBuffer extends IGLTFChildRootProperty {
+        uri?: string;
+        byteLength: number;
+
+        // Loaded buffer (optimize)
+        loadedBufferView: ArrayBufferView
+    }
+
+    export interface IGLTFBufferView extends IGLTFChildRootProperty {
+        buffer: number;
+        byteOffset: number;
+        byteLength: number;
+        byteStride?: number;
+        target?: EBufferViewTarget;
+    }
+
+    export interface IGLTFCameraOrthographic extends IGLTFProperty {
+        xmag: number;
+        ymag: number;
+        zfar: number;
+        znear: number;
+    }
+
+    export interface IGLTFCameraPerspective extends IGLTFProperty {
+        aspectRatio: number;
+        yfov: number;
+        zfar: number;
+        znear: number;
+    }
+
+    export interface IGLTFCamera extends IGLTFChildRootProperty {
+        orthographic?: IGLTFCameraOrthographic;
+        perspective?: IGLTFCameraPerspective;
+        type: string;
+    }
+
+    export interface IGLTFImage extends IGLTFChildRootProperty {
+        uri?: string;
+        mimeType?: string;
+        bufferView?: number;
+    }
+
+    export interface IGLTFMaterialNormalTextureInfo extends IGLTFTextureInfo {
+        scale: number;
+    }
+
+    export interface IGLTFMaterialOcclusionTextureInfo extends IGLTFTextureInfo {
+        strength: number;
+    }
+
+    export interface IGLTFMaterialPbrMetallicRoughness {
+        baseColorFactor: number[];
+        baseColorTexture: IGLTFTextureInfo;
+        metallicFactor: number;
+        roughnessFactor: number;
+        metallicRoughnessTexture: IGLTFTextureInfo;
+    }
+
+    export interface IGLTFMaterial extends IGLTFChildRootProperty {
+        pbrMetallicRoughness?: IGLTFMaterialPbrMetallicRoughness;
+        normalTexture?: IGLTFMaterialNormalTextureInfo;
+        occlusionTexture?: IGLTFMaterialOcclusionTextureInfo;
+        emissiveTexture?: IGLTFTextureInfo;
+        emissiveFactor?: number[];
+        alphaMode?: string;
+        alphaCutoff: number;
+        doubleSided?: boolean;
+
+        // Babylon.js values (optimize)
+        babylonMaterial?: PBRMaterial;
+    }
+
+    export interface IGLTFMeshPrimitive extends IGLTFProperty {
+        attributes: { [name: string]: number };
+        indices?: number;
+        material?: number;
+        mode?: EMeshPrimitiveMode;
+        targets?: number[];
+    }
+
+    export interface IGLTFMesh extends IGLTFChildRootProperty {
+        primitives: IGLTFMeshPrimitive[];
+        weights?: number[];
+    }
+
+    export interface IGLTFNode extends IGLTFChildRootProperty {
+        camera?: number;
+        children?: number[];
+        skin?: number;
+        matrix?: number[];
+        mesh?: number;
+        rotation?: number[];
+        scale?: number[];
+        translation?: number[];
+        weights?: number[];
+
+        // Babylon.js values (optimize)
+        babylonNode?: Node;
+    }
+
+    export interface IGLTFSampler extends IGLTFChildRootProperty {
+        magFilter?: ETextureMagFilter;
+        minFilter?: ETextureMinFilter;
+        wrapS?: ETextureWrapMode;
+        wrapT?: ETextureWrapMode;
+    }
+
+    export interface IGLTFScene extends IGLTFChildRootProperty {
+        nodes: number[];
+    }
+
+    export interface IGLTFSkin extends IGLTFChildRootProperty {
+        inverseBindMatrices?: number;
+        skeleton?: number;
+        joints: number[];
+
+        // Babylon.js values (optimize)
+        babylonSkeleton?: Skeleton;
+    }
+
+    export interface IGLTFTexture extends IGLTFChildRootProperty {
+        format?: ETextureFormat;
+        internalFormat?: ETextureFormat;
+        sampler: number;
+        source: number;
+        target?: ETextureTarget;
+        type?: ETextureType;
+
+        // 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[];
+
+        defaultMaterial?: PBRMaterial;
+    }
+
+    /**
+    * Bones
+    */
+    export interface INodeToRoot {
+        bone: Bone;
+        node: IGLTFNode;
+        index: number;
+    }
+
+    export interface IJointNode {
+        node: IGLTFNode;
+        index: number;
+    }
+}

+ 141 - 0
loaders/src/glTF/2.0/babylon.glTFLoaderUtils.ts

@@ -0,0 +1,141 @@
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GLTF2 {
+    /**
+    * Utils functions for GLTF
+    */
+    export class GLTFUtils {
+        /**
+        * If the uri is a base64 string
+        * @param uri: the uri to test
+        */
+        public static IsBase64(uri: string): boolean {
+            return uri.length < 5 ? false : uri.substr(0, 5) === "data:";
+        }
+
+        /**
+        * Decode the base64 uri
+        * @param uri: the uri to decode
+        */
+        public static DecodeBase64(uri: string): ArrayBuffer {
+            var decodedString = atob(uri.split(",")[1]);
+            var bufferLength = decodedString.length;
+            var bufferView = new Uint8Array(new ArrayBuffer(bufferLength));
+
+            for (var i = 0; i < bufferLength; i++) {
+                bufferView[i] = decodedString.charCodeAt(i);
+            }
+
+            return bufferView.buffer;
+        }
+
+        /**
+        * Returns the wrap mode of the texture
+        * @param mode: the mode value
+        */
+        public static GetWrapMode(mode: number): number {
+            switch (mode) {
+                case ETextureWrapMode.CLAMP_TO_EDGE: return Texture.CLAMP_ADDRESSMODE;
+                case ETextureWrapMode.MIRRORED_REPEAT: return Texture.MIRROR_ADDRESSMODE;
+                case ETextureWrapMode.REPEAT: return Texture.WRAP_ADDRESSMODE;
+                default: return Texture.WRAP_ADDRESSMODE;
+            }
+        }
+
+        /**
+         * Returns the byte stride giving an accessor
+         * @param accessor: the GLTF accessor objet
+         */
+        public static GetByteStrideFromType(accessor: IGLTFAccessor): number {
+            // Needs this function since "byteStride" isn't requiered in glTF format
+            var type = accessor.type;
+
+            switch (type) {
+                case "VEC2": return 2;
+                case "VEC3": return 3;
+                case "VEC4": return 4;
+                case "MAT2": return 4;
+                case "MAT3": return 9;
+                case "MAT4": return 16;
+                default: return 1;
+            }
+        }
+
+        /**
+         * Returns the texture filter mode giving a mode value
+         * @param mode: the filter mode value
+         */
+        public static GetTextureFilterMode(mode: number): ETextureMinFilter {
+            switch (mode) {
+                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(runtime: IGLTFRuntime, bufferView: IGLTFBufferView, byteOffset: number, byteLength: number, componentType: EComponentType): ArrayBufferView {
+            var byteOffset = bufferView.byteOffset + byteOffset;
+
+            var loadedBufferView = runtime.gltf.buffers[bufferView.buffer].loadedBufferView;
+            if (byteOffset + byteLength > loadedBufferView.byteLength) {
+                throw new Error("Buffer access is out of range");
+            }
+
+            var buffer = loadedBufferView.buffer;
+            byteOffset += loadedBufferView.byteOffset;
+
+            switch (componentType) {
+                case EComponentType.BYTE: return new Int8Array(buffer, byteOffset, byteLength);
+                case EComponentType.UNSIGNED_BYTE: return new Uint8Array(buffer, byteOffset, byteLength);
+                case EComponentType.SHORT: return new Int16Array(buffer, byteOffset, byteLength);
+                case EComponentType.UNSIGNED_SHORT: return new Uint16Array(buffer, byteOffset, byteLength);
+                default: return new Float32Array(buffer, byteOffset, byteLength);
+            }
+        }
+
+        /**
+         * Returns a buffer from its accessor
+         * @param runtime: the GLTF runtime
+         * @param accessor: the GLTF accessor
+         */
+        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(runtime, bufferView, accessor.byteOffset, byteLength, accessor.componentType);
+        }
+
+        /**
+         * Decodes a buffer view into a string
+         * @param view: the buffer view
+         */
+        public static DecodeBufferToText(view: ArrayBufferView): string {
+            var result = "";
+            var length = view.byteLength;
+
+            for (var i = 0; i < length; ++i) {
+                result += String.fromCharCode(view[i]);
+            }
+
+            return result;
+        }
+
+        /**
+         * Returns the default material of gltf.
+         * @param scene: the Babylon.js scene
+         */
+        public static GetDefaultMaterial(runtime: IGLTFRuntime): PBRMaterial {
+            if (!runtime.defaultMaterial) {
+                var material = new PBRMaterial("gltf_default", runtime.babylonScene);
+                material.sideOrientation = Material.CounterClockWiseSideOrientation;
+                material.metallic = 1;
+                material.roughness = 1;
+                runtime.defaultMaterial = material;
+            }
+
+            return runtime.defaultMaterial;
+        }
+    }
+}

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

@@ -0,0 +1,56 @@
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GLTF2 {
+    interface IGLTFMaterialsPbrSpecularGlossiness {
+        diffuseFactor: number[];
+        diffuseTexture: IGLTFTextureInfo;
+        specularFactor: number[];
+        glossinessFactor: number;
+        specularGlossinessTexture: IGLTFTextureInfo;
+    }
+
+    export class GLTFMaterialsPbrSpecularGlossinessExtension extends GLTFLoaderExtension {
+        constructor() {
+            super("KHR_materials_pbrSpecularGlossiness");
+        }
+
+        protected loadMaterial(runtime: IGLTFRuntime, index: number): boolean {
+            var material = GLTFLoader.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) {
+                GLTFLoader.LoadTextureAsync(runtime, properties.diffuseTexture,
+                    texture => {
+                        material.babylonMaterial.albedoTexture = texture;
+                        GLTFLoader.LoadAlphaProperties(runtime, material);
+                    },
+                    () => {
+                        Tools.Warn("Failed to load diffuse texture");
+                    });
+            }
+
+            if (properties.specularGlossinessTexture) {
+                GLTFLoader.LoadTextureAsync(runtime, properties.specularGlossinessTexture,
+                    texture => {
+                        material.babylonMaterial.reflectivityTexture = texture;
+                        material.babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true;
+                    },
+                    () => {
+                        Tools.Warn("Failed to load metallic roughness texture");
+                    });
+            }
+
+            GLTFLoader.LoadCommonMaterialProperties(runtime, material);
+            return true;
+        }
+    }
+
+    GLTFLoader.RegisterExtension(new GLTFMaterialsPbrSpecularGlossinessExtension());
+}

+ 25 - 14
loaders/src/glTF/README.md

@@ -1,12 +1,28 @@
 # Babylon.js glTF File Loader
 
 # Usage
-The glTF file loader is a SceneLoader plugin.
-Just reference the loader in your HTML file:
+The glTF file loader is a SceneLoader plugin. The loader supports glTF version 1.0 and 2.0 and will use the correct loader based on the glTF version string. Include the version support that you want in any combination.
 
+Both versions:
 ```
-<script src="babylon.2.2.js"></script>
+<script src="babylon.js"></script>
 <script src="babylon.glTFFileLoader.js"></script>
+<script src="babylon.glTF1Loader.js"></script>
+<script src="babylon.glTF2Loader.js"></script>
+```
+
+Version 1 only:
+```
+<script src="babylon.js"></script>
+<script src="babylon.glTFFileLoader.js"></script>
+<script src="babylon.glTF1Loader.js"></script>
+```
+
+Version 2 only:
+```
+<script src="babylon.js"></script>
+<script src="babylon.glTFFileLoader.js"></script>
+<script src="babylon.glTF2Loader.js"></script>
 ```
 
 And then, call the scene loader:
@@ -24,19 +40,13 @@ BABYLON.SceneLoader.ImportMesh(["myMesh1", "myMesh2", "..."], "./", "duck.gltf",
 });
 ```
 
-In order the fix the UP vector (Y with Babylon.js) if you want to play with physics, you can customize the loader:
-```
-BABYLON.GLTFFileLoader.MakeYUP = true; // false by default
-```
-
-If you want to disable incremental loading (which is the default behavior), you can set the property IncrementalLoading to false.
-Then, you'll be able to be called back with all geometries and shaders loaded.
-For example, you can retrieve the real bounding infos of a mesh loaded using the loader.
+If you want to disable incremental loading, you can set the property `IncrementalLoading` to false.
+Then, you'll be able to be called back with all geometries, shaders (V1), PBR materials (V2) loaded. Textures are always loaded asynchronously. For example, you can retrieve the real bounding infos of a mesh loaded when incremental loading is disabled.
 ```
 BABYLON.GLTFFileLoader.IncrementalLoading = false; // true by default
 ```
 
-In order to work with homogeneous coordinates (that can be available with some converters and exporters):
+(V1 only) In order to work with homogeneous coordinates (that can be available with some converters and exporters):
 ```
 BABYLON.GLTFFileLoader.HomogeneousCoordinates = true; // false by default
 ```
@@ -47,9 +57,9 @@ BABYLON.GLTFFileLoader.HomogeneousCoordinates = true; // false by default
 * Import geometries
     * From binary files
     * From base64 buffers
-* Import lights
+* Import lights (V1 only)
 * Import cameras
-* Import and set custom shaders
+* Import and set custom shaders (V1 only)
     * Automatically bind attributes
     * Automatically bind matrices
     * Set uniforms
@@ -59,6 +69,7 @@ BABYLON.GLTFFileLoader.HomogeneousCoordinates = true; // false by default
     * Hardware skinning (shaders support)
     * Bones import
 * Handle dummy nodes (empty nodes)
+* PBR materials (V2 only)
 
 ## To improve
 * Test on more geometries

文件差異過大導致無法顯示
+ 181 - 1664
loaders/src/glTF/babylon.glTFFileLoader.ts


+ 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"]
+  }
 }

+ 5 - 5
localDev/src/index.js

@@ -49,20 +49,20 @@ var createScene = function()
     sphere.subMeshes.push(new BABYLON.SubMesh(1, 0, verticesCount, 900, 900, sphere));
     sphere.subMeshes.push(new BABYLON.SubMesh(2, 0, verticesCount, 1800, 2088, sphere));
 
-  //  material0.diffuseTexture = new BABYLON.Texture("textures/misc.jpg", scene, true, true, BABYLON.Texture.BILINEAR_SAMPLINGMODE); 
+ //   material0.diffuseTexture = new BABYLON.Texture("/assets/textures/leopard_fur.jpg", scene, true, true, BABYLON.Texture.BILINEAR_SAMPLINGMODE); 
 
     scene.actionManager = new BABYLON.ActionManager(scene);
     scene.actionManager.registerAction(new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnKeyUpTrigger, function (evt) {
         if (evt.sourceEvent.key == "t")
         {
-          //  globals.multimat.subMaterials[0].diffuseColor = new BABYLON.Color3(1, 1, 1);
-            globals.multimat.subMaterials[0].diffuseTexture = new BABYLON.Texture("/assets/textures/amiga.jpg", scene, true, true, BABYLON.Texture.BILINEAR_SAMPLINGMODE);
+            globals.multimat.subMaterials[0].diffuseColor = new BABYLON.Color3(1, 1, 1);
+            globals.multimat.subMaterials[0].diffuseTexture = new BABYLON.Texture("/assets/textures/leopard_fur.jpg", scene, true, true, BABYLON.Texture.BILINEAR_SAMPLINGMODE);
         }
         else if (evt.sourceEvent.key == "m")
         {
             var material0 = new BABYLON.StandardMaterial("mat0", scene);
-          //  material0.diffuseColor = new BABYLON.Color3(0, 1, 0);
-            material0.diffuseTexture = new BABYLON.Texture("/assets/textures/amiga.jpg", scene, true, true, BABYLON.Texture.BILINEAR_SAMPLINGMODE);
+            material0.diffuseColor = new BABYLON.Color3(0, 1, 0);
+            material0.diffuseTexture = new BABYLON.Texture("/assets/textures/leopard_fur.jpg", scene, true, true, BABYLON.Texture.BILINEAR_SAMPLINGMODE);
 
             globals.multimat.subMaterials[0] = material0; 
         }

+ 0 - 2
src/Layer/babylon.highlightlayer.ts

@@ -299,7 +299,6 @@ module BABYLON {
             this._glowMapMergeEffect = engine.createEffect("glowMapMerge",
                 [VertexBuffer.PositionKind],
                 ["offset"],
-                [],
                 ["textureSampler"], "");
 
             // Render target
@@ -583,7 +582,6 @@ module BABYLON {
                 this._glowMapGenerationEffect = this._scene.getEngine().createEffect("glowMapGeneration",
                     attribs,
                     ["world", "mBones", "viewProjection", "diffuseMatrix", "color", "emissiveMatrix"],
-                    [],
                     ["diffuseSampler", "emissiveSampler"], join);
             }
 

+ 0 - 2
src/Layer/babylon.layer.ts

@@ -95,13 +95,11 @@
             this._effect = engine.createEffect("layer",
                 [VertexBuffer.PositionKind],
                 ["textureMatrix", "color", "scale", "offset"],
-                [],
                 ["textureSampler"], "");
 
             this._alphaTestEffect = engine.createEffect("layer",
                 [VertexBuffer.PositionKind],
                 ["textureMatrix", "color", "scale", "offset"],
-                [],
                 ["textureSampler"], "#define ALPHATEST");
         }
 

+ 0 - 1
src/LensFlare/babylon.lensFlareSystem.ts

@@ -52,7 +52,6 @@
             this._effect = engine.createEffect("lensFlare",
                 [VertexBuffer.PositionKind],
                 ["color", "viewportMatrix"],
-                [],
                 ["textureSampler"], "");
         }
 

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

@@ -394,7 +394,6 @@
                 this._effect = this._scene.getEngine().createEffect("shadowMap",
                     attribs,
                     ["world", "mBones", "viewProjection", "diffuseMatrix", "lightPosition", "depthValues", "biasAndScale"],
-                    [],
                     ["diffuseSampler"], join);
             }
 

+ 0 - 1
src/Materials/Textures/Procedurals/babylon.proceduralTexture.ts

@@ -107,7 +107,6 @@
             this._effect = engine.createEffect(shaders,
                 [VertexBuffer.PositionKind],
                 this._uniforms,
-                [],
                 this._samplers,
                 "", null, null, () => {
                     this.releaseInternalTexture();

+ 45 - 15
src/Materials/babylon.effect.ts

@@ -71,6 +71,18 @@
         }
     }
 
+    export class EffectCreationOptions {
+        public attributes: string[];
+        public uniformsNames: string[];
+        public uniformBuffersNames: string[];
+        public samplers: string[];
+        public defines: string;
+        public fallbacks: EffectFallbacks;
+        public onCompiled: (effect: Effect) => void;
+        public onError: (effect: Effect, errors: string) => void;
+        public indexParameters: any;
+    }
+
     export class Effect {
         public name: any;
         public defines: string;
@@ -91,28 +103,46 @@
         private _uniforms: WebGLUniformLocation[];
         public _key: string;
         private _indexParameters: any;
+        private _fallbacks: EffectFallbacks;
 
         private _program: WebGLProgram;
         private _valueCache: { [key: string]: any } = {};
 
-        constructor(baseName: any, attributesNames: string[], uniformsNames: string[], uniformBuffers: string[], samplers: string[], engine, defines?: string, fallbacks?: EffectFallbacks, onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void, indexParameters?: any) {
-            this._engine = engine;
+        constructor(baseName: any, attributesNamesOrOptions: string[] | EffectCreationOptions, uniformsNamesOrEngine: string[] | Engine, samplers?: string[], engine?: Engine, defines?: string, fallbacks?: EffectFallbacks, onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void, indexParameters?: any) {
             this.name = baseName;
-            this.defines = defines;
 
-            for (var i = 0; i < uniformBuffers.length; i++) {
-                this._uniformBuffersNames[uniformBuffers[i]] = i;
-            }
-
-            this._uniformsNames = uniformsNames.concat(samplers);
-            this._samplers = samplers;
-            this._attributesNames = attributesNames;
-
-            this.onError = onError;
-            this.onCompiled = onCompiled;
+            if ((<EffectCreationOptions>attributesNamesOrOptions).attributes) {
+                var options = <EffectCreationOptions>attributesNamesOrOptions;
+                this._engine = <Engine>uniformsNamesOrEngine;
+
+                this._attributesNames = options.attributes;
+                this._uniformsNames = options.uniformsNames.concat(options.samplers);
+                this._samplers = options.samplers;
+                this.defines = options.defines;
+                this.onError = options.onError;
+                this.onCompiled = options.onCompiled;
+                this._fallbacks = options.fallbacks;
+                this._indexParameters = options.indexParameters;  
+
+                if (options.uniformBuffersNames) {
+                    for (var i = 0; i < options.uniformBuffersNames.length; i++) {
+                        this._uniformBuffersNames[options.uniformBuffersNames[i]] = i;
+                    }          
+                }    
+            } else {
+                this._engine = engine;
+                this.defines = defines;
+                this._uniformsNames = (<string[]>uniformsNamesOrEngine).concat(samplers);
+                this._samplers = samplers;
+                this._attributesNames = (<string[]>attributesNamesOrOptions);
 
-            this._indexParameters = indexParameters;
+                this.onError = onError;
+                this.onCompiled = onCompiled;
 
+                this._indexParameters = indexParameters;
+                this._fallbacks = fallbacks;
+            }
+        
             this.uniqueId = Effect._uniqueIdSeed++;
 
             var vertexSource;
@@ -144,7 +174,7 @@
                         this._loadFragmentShader(fragmentSource, (fragmentCode) => {
                             this._processIncludes(fragmentCode, fragmentCodeWithIncludes => {
                                 this._processShaderConversion(fragmentCodeWithIncludes, true, migratedFragmentCode => {
-                                    this._prepareEffect(migratedVertexCode, migratedFragmentCode, attributesNames, defines, fallbacks);
+                                    this._prepareEffect(migratedVertexCode, migratedFragmentCode, this._attributesNames, this.defines, this._fallbacks);
                                 });
                             });
                         });

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

@@ -33,6 +33,15 @@
             this._isDirty = true;
         }
 
+        public markAllAsDirty() {
+            this._areTexturesDirty = true;
+            this._areAttributesDirty = true;
+            this._areLightsDirty = true;
+            this._areFresnelDirty = true;
+            this._areMiscDirty = true;
+            this._isDirty = true;
+        }
+
         public markAsLightDirty() {
             this._areLightsDirty = true;
             this._isDirty = true;

+ 3 - 3
src/Materials/babylon.materialHelper.ts

@@ -111,11 +111,11 @@
                     defines["DIRLIGHT" + lightIndex] = false;
 
                     var type;
-                    if (light instanceof SpotLight) {
+                    if (light.getTypeID() === 2) {
                         type = "SPOTLIGHT" + lightIndex;
-                    } else if (light instanceof HemisphericLight) {
+                    } else if (light.getTypeID() === 3) {
                         type = "HEMILIGHT" + lightIndex;
-                    } else if (light instanceof PointLight) {
+                    } else if (light.getTypeID() === 0) {
                         type = "POINTLIGHT" + lightIndex;
                     } else {
                         type = "DIRLIGHT" + lightIndex;

+ 11 - 4
src/Materials/babylon.pbrMaterial.ts

@@ -2,6 +2,7 @@
     class PBRMaterialDefines extends MaterialDefines {
         public ALBEDO = false;
         public AMBIENT = false;
+        public AMBIENTINGRAYSCALE = false;
         public OPACITY = false;
         public OPACITYRGB = false;
         public REFLECTION = false;
@@ -335,7 +336,7 @@
 
         @serializeAsColor3("ambient")
         public ambientColor = new Color3(0, 0, 0);
-        
+
         /**
          * AKA Diffuse Color in other nomenclature.
          */
@@ -443,6 +444,12 @@
          */
         @serialize()
         public useAmbientOcclusionFromMetallicTextureRed = false;
+
+        /**
+         * Specifies if the ambient texture contains the ambient occlusion information in its red channel only.
+         */
+        @serialize()
+        public useAmbientInGrayScale = false;
         
         /**
          * In case the reflectivity map does not contain the microsurface information in its alpha channel,
@@ -698,9 +705,10 @@
                     if (!this.ambientTexture.isReady()) {
                         return false;
                     }
-                    
+
                     needUVs = true;
                     this._defines.AMBIENT = true;
+                    this._defines.AMBIENTINGRAYSCALE = this.useAmbientInGrayScale;
                 }
 
                 if (this.opacityTexture && StandardMaterial.OpacityTextureEnabled) {
@@ -1150,7 +1158,6 @@
                 
                 this._effect = scene.getEngine().createEffect("pbr",
                     attribs, uniforms, 
-                    [],
                     samplers,
                     join, fallbacks, this.onCompiled, this.onError, {maxSimultaneousLights: this.maxSimultaneousLights, maxSimultaneousMorphTargets: this._defines.NUM_MORPH_INFLUENCERS});
             }
@@ -1291,7 +1298,7 @@
                         if (this.metallicTexture) {
                             this._effect.setTexture("reflectivitySampler", this.metallicTexture);
 
-                            this._effect.setFloat3("vReflectivityInfos", this.metallicTexture.coordinatesIndex, this.reflectivityTexture.level, this.ambientTextureStrength);
+                            this._effect.setFloat3("vReflectivityInfos", this.metallicTexture.coordinatesIndex, this.metallicTexture.level, this.ambientTextureStrength);
                             this._effect.setMatrix("reflectivityMatrix", this.metallicTexture.getTextureMatrix());
                         }
                         else if (this.reflectivityTexture) {

+ 10 - 6
src/Materials/babylon.shaderMaterial.ts

@@ -206,12 +206,16 @@
             var previousEffect = this._effect;
             var join = defines.join("\n");
 
-            this._effect = engine.createEffect(this._shaderPath,
-                this._options.attributes,
-                this._options.uniforms,
-                this._options.uniformBuffers,
-                this._options.samplers,
-                join, fallbacks, this.onCompiled, this.onError);
+            this._effect = engine.createEffect(this._shaderPath, <EffectCreationOptions>{
+                    attributes: this._options.attributes,
+                    uniformsNames: this._options.uniforms,
+                    uniformBuffersNames: this._options.uniformBuffers,
+                    samplers: this._options.samplers,
+                    defines: join,
+                    fallbacks: fallbacks,
+                    onCompiled: this.onCompiled,
+                    onError: this.onError
+                }, engine);
 
             if (!this._effect.isReady()) {
                 return false;

+ 12 - 6
src/Materials/babylon.standardMaterial.ts

@@ -728,13 +728,19 @@ module BABYLON {
                     this.bindTransformMatrix(effect, scene.getTransformMatrixBuffer());
                 }.bind(this);
 
-                subMesh.setEffect(scene.getEngine().createEffect(shaderName,
-                    attribs, uniforms, uniformBuffers, samplers,
-                    join, fallbacks, onCompiled, this.onError, { maxSimultaneousLights: this._maxSimultaneousLights, maxSimultaneousMorphTargets: defines.NUM_MORPH_INFLUENCERS }), defines);
-
+                subMesh.setEffect(scene.getEngine().createEffect(shaderName, {
+                    attributes: attribs,
+                    uniformsNames: uniforms,
+                    uniformBuffersNames: uniformBuffers,
+                    samplers: samplers,
+                    defines: join,
+                    fallbacks: fallbacks,
+                    onCompiled: onCompiled,
+                    onError: this.onError,
+                    indexParameters: { maxSimultaneousLights: this._maxSimultaneousLights, maxSimultaneousMorphTargets: defines.NUM_MORPH_INFLUENCERS }
+                }, engine), defines);
+                
                 this.buildUniformLayout();
-
-
             }
 
             if (!subMesh.effect.isReady()) {

+ 2 - 2
src/Mesh/babylon.geometry.ts

@@ -65,8 +65,8 @@
 
             // applyToMesh
             if (mesh) {
-                if (mesh instanceof LinesMesh) {
-                    this.boundingBias = new Vector2(0, mesh.intersectionThreshold);
+                if (mesh.getClassName() === "LinesMesh") {
+                    this.boundingBias = new Vector2(0, (<LinesMesh> mesh).intersectionThreshold);
                     this.updateExtend();
                 }
 

+ 12 - 2
src/Mesh/babylon.subMesh.ts

@@ -17,6 +17,7 @@
 
         public _materialDefines: MaterialDefines;
         private _materialEffect: Effect;
+        private _currentMaterial: Material;
 
         public get effect(): Effect {
             return this._materialEffect;
@@ -89,9 +90,18 @@
         public getMaterial(): Material {
             var rootMaterial = this._renderingMesh.material;
 
-            if (rootMaterial && rootMaterial instanceof MultiMaterial) {
+            if (rootMaterial && (<MultiMaterial>rootMaterial).getSubMaterial) {
                 var multiMaterial = <MultiMaterial>rootMaterial;
-                return multiMaterial.getSubMaterial(this.materialIndex);
+                var effectiveMaterial = multiMaterial.getSubMaterial(this.materialIndex);
+
+                if (this._currentMaterial !== effectiveMaterial) {
+                    this._currentMaterial = effectiveMaterial;
+                    if (this._materialDefines) {
+                        this._materialDefines.markAllAsDirty();
+                    }
+                }
+
+                return effectiveMaterial;
             }
 
             if (!rootMaterial) {

+ 0 - 1
src/Particles/babylon.particleSystem.ts

@@ -298,7 +298,6 @@
                     "particles",
                     [VertexBuffer.PositionKind, VertexBuffer.ColorKind, "options"],
                     ["invView", "view", "projection", "vClipPlane", "textureMask"],
-                    [],
                     ["diffuseSampler"], join);
             }
 

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

@@ -133,7 +133,6 @@
             this._effect = this._engine.createEffect({ vertex: "postprocess", fragment: this._fragmentUrl },
                 ["position"],
                 this._parameters,
-                [],
                 this._samplers, defines !== undefined ? defines : "");
         }
 

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

@@ -188,7 +188,6 @@
                     { vertexElement: "depth", fragmentElement: "volumetricLightScatteringPass" },
                     attribs,
                     ["world", "mBones", "viewProjection", "diffuseMatrix"],
-                    [],
                     ["diffuseSampler"], join);
             }
 

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

@@ -142,7 +142,6 @@
                 this._effect = this._scene.getEngine().createEffect("depth",
                     attribs,
                     ["world", "mBones", "viewProjection", "diffuseMatrix", "far"],
-                    [],
                     ["diffuseSampler"], join);
             }
 

+ 0 - 1
src/Rendering/babylon.outlineRenderer.ts

@@ -94,7 +94,6 @@
                 this._effect = this._scene.getEngine().createEffect("outline",
                     attribs,
                     ["world", "mBones", "viewProjection", "diffuseMatrix", "offset", "color"],
-                    [],
                     ["diffuseSampler"], join);
             }
 

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

@@ -245,6 +245,9 @@ void main(void) {
 
 #ifdef AMBIENT
 	vec3 ambientOcclusionColorMap = texture2D(ambientSampler, vAmbientUV + uvOffset).rgb * vAmbientInfos.y;
+	#ifdef AMBIENTINGRAYSCALE			
+		ambientOcclusionColorMap = vec3(ambientOcclusionColorMap.r, ambientOcclusionColorMap.r, ambientOcclusionColorMap.r);
+	#endif
 	ambientOcclusionColor = mix(ambientOcclusionColor, ambientOcclusionColorMap, vAmbientInfos.z);
 
 	#ifdef OVERLOADEDVALUES
@@ -316,13 +319,13 @@ void main(void) {
 	// Diffuse is used as the base of the reflectivity.
 	vec3 baseColor = surfaceAlbedo.rgb;
 
-	// Drop the surface diffuse by the 1.0 - metalness.
-	surfaceAlbedo.rgb *= (1.0 - metallicRoughness.r);
-	
-	// Default specular reflectance at normal incidence aka F0.
+	// Default specular reflectance at normal incidence.
 	// 4% corresponds to index of refraction (IOR) of 1.50, approximately equal to glass.
 	const vec3 DefaultSpecularReflectanceDielectric = vec3(0.04, 0.04, 0.04);
 
+	// Compute the converted diffuse.
+	surfaceAlbedo.rgb = mix(baseColor.rgb * (1.0 - DefaultSpecularReflectanceDielectric.r), vec3(0., 0., 0.), metallicRoughness.r);
+
 	// Compute the converted reflectivity.
 	surfaceReflectivityColor = mix(DefaultSpecularReflectanceDielectric, baseColor, metallicRoughness.r);
 

+ 0 - 2
src/Sprites/babylon.spriteManager.ts

@@ -96,13 +96,11 @@
             this._effectBase = this._scene.getEngine().createEffect("sprites",
                 [VertexBuffer.PositionKind, "options", "cellInfo", VertexBuffer.ColorKind],
                 ["view", "projection", "textureInfos", "alphaTest"],
-                [],
                 ["diffuseSampler"], "");
 
             this._effectFog = this._scene.getEngine().createEffect("sprites",
                 [VertexBuffer.PositionKind, "options", "cellInfo", VertexBuffer.ColorKind],
                 ["view", "projection", "textureInfos", "alphaTest", "vFogInfos", "vFogColor"],
-                [],
                 ["diffuseSampler"], "#define FOG");
         }
 

+ 9 - 11
src/babylon.engine.ts

@@ -779,9 +779,6 @@
                 Engine.audioEngine = new AudioEngine();
             }
 
-            //default loading screen
-            this._loadingScreen = new DefaultLoadingScreen(this._renderingCanvas);
-
             //Load WebVR Devices
             if (options.autoEnableWebVR) {
                 this.initWebVR();
@@ -1808,17 +1805,18 @@
             }
         }
 
-        public createEffect(baseName: any, attributesNames: string[], uniformsNames: string[], uniformBuffers: string[], samplers: string[], defines: string, fallbacks?: EffectFallbacks,
+        
+        public createEffect(baseName: any, attributesNamesOrOptions: string[] | EffectCreationOptions, uniformsNamesOrEngine: string[] | Engine, samplers?: string[], defines?: string, fallbacks?: EffectFallbacks,
             onCompiled?: (effect: Effect) => void, onError?: (effect: Effect, errors: string) => void, indexParameters?: any): Effect {
             var vertex = baseName.vertexElement || baseName.vertex || baseName;
             var fragment = baseName.fragmentElement || baseName.fragment || baseName;
 
-            var name = vertex + "+" + fragment + "@" + defines;
+            var name = vertex + "+" + fragment + "@" + (defines ? defines : (<EffectCreationOptions>attributesNamesOrOptions).defines);
             if (this._compiledEffects[name]) {
                 return this._compiledEffects[name];
             }
 
-            var effect = new Effect(baseName, attributesNames, uniformsNames, uniformBuffers, samplers, this, defines, fallbacks, onCompiled, onError, indexParameters);
+            var effect = new Effect(baseName, attributesNamesOrOptions, uniformsNamesOrEngine, samplers, this, defines, fallbacks, onCompiled, onError, indexParameters);
             effect._key = name;
             this._compiledEffects[name] = effect;
 
@@ -1835,7 +1833,6 @@
                 },
                 ["position", "color", "options"],
                 ["view", "projection"].concat(uniformsNames),
-                [],
                 ["diffuseSampler"].concat(samplers), defines, fallbacks, onCompiled, onError);
         }
 
@@ -3435,14 +3432,15 @@
 
         // Loading screen
         public displayLoadingUI(): void {
-            this._loadingScreen.displayLoadingUI();
+            this.loadingScreen.displayLoadingUI();
         }
 
         public hideLoadingUI(): void {
-            this._loadingScreen.hideLoadingUI();
+            this.loadingScreen.hideLoadingUI();
         }
 
         public get loadingScreen(): ILoadingScreen {
+            if (!this._loadingScreen) this._loadingScreen = new DefaultLoadingScreen(this._renderingCanvas)
             return this._loadingScreen;
         }
 
@@ -3451,11 +3449,11 @@
         }
 
         public set loadingUIText(text: string) {
-            this._loadingScreen.loadingUIText = text;
+            this.loadingScreen.loadingUIText = text;
         }
 
         public set loadingUIBackgroundColor(color: string) {
-            this._loadingScreen.loadingUIBackgroundColor = color;
+            this.loadingScreen.loadingUIBackgroundColor = color;
         }
 
         public attachContextLostEvent(callback: ((event: WebGLContextEvent) => void)): void {