Forráskód Böngészése

Add support for KHR_materials_unlit to glTF loader

Gary Hsu 7 éve
szülő
commit
f90c0a016b

+ 2 - 0
Tools/Gulp/config.json

@@ -1530,6 +1530,7 @@
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_lod.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_lights.ts"
                 ],
                 "doNotIncludeInBundle": true,
@@ -1551,6 +1552,7 @@
                     "../../loaders/src/glTF/2.0/Extensions/MSFT_lod.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts",
+                    "../../loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts",
                     "../../loaders/src/glTF/2.0/Extensions/KHR_lights.ts"
                 ],
                 "output": "babylon.glTFFileLoader.js"

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

@@ -109,6 +109,7 @@
 - Earcut is an external, optional dependency. ([RaananW](https://github.com/RaananW))
 - Return animation groups when calling `SceneLoader.ImportMesh`. ([bghgary](https://github.com/bghgary)]
 - Add support for normalized and non-float data to `Buffer` and `VertexBuffer`. ([bghgary](https://github.com/bghgary)]
+- Added unlit material extension support to glTF 2.0 loader. ([bghgary](https://github.com/bghgary))
 
 ## Bug fixes
 

+ 9 - 9
loaders/src/glTF/2.0/Extensions/KHR_lights.ts

@@ -35,12 +35,12 @@ module BABYLON.GLTF2.Extensions {
         public readonly name = NAME;
 
         protected _loadSceneAsync(context: string, scene: ILoaderScene): Nullable<Promise<void>> { 
-            return this._loadExtensionAsync<ILightReference>(context, scene, (context, extension) => {
-                const promise = this._loader._loadSceneAsync(context, scene);
+            return this._loadExtensionAsync<ILightReference>(context, scene, (extensionContext, extension) => {
+                const promise = this._loader._loadSceneAsync(extensionContext, scene);
 
-                const light = GLTFLoader._GetProperty(context, this._lights, extension.light);
+                const light = GLTFLoader._GetProperty(extensionContext, this._lights, extension.light);
                 if (light.type !== LightType.AMBIENT) {
-                    throw new Error(`${context}: Only ambient lights are allowed on a scene`);
+                    throw new Error(`${extensionContext}: Only ambient lights are allowed on a scene`);
                 }
 
                 this._loader._babylonScene.ambientColor = light.color ? Color3.FromArray(light.color) : Color3.Black();
@@ -50,16 +50,16 @@ module BABYLON.GLTF2.Extensions {
         }
 
         protected _loadNodeAsync(context: string, node: ILoaderNode): Nullable<Promise<void>> { 
-            return this._loadExtensionAsync<ILightReference>(context, node, (context, extension) => {
-                const promise = this._loader._loadNodeAsync(context, node);
+            return this._loadExtensionAsync<ILightReference>(context, node, (extensionContext, extension) => {
+                const promise = this._loader._loadNodeAsync(extensionContext, node);
 
                 let babylonLight: Light;
 
-                const light = GLTFLoader._GetProperty(context, this._lights, extension.light);
+                const light = GLTFLoader._GetProperty(extensionContext, this._lights, extension.light);
                 const name = node._babylonMesh!.name;
                 switch (light.type) {
                     case LightType.AMBIENT: {
-                        throw new Error(`${context}: Ambient lights are not allowed on a node`);
+                        throw new Error(`${extensionContext}: Ambient lights are not allowed on a node`);
                     }
                     case LightType.DIRECTIONAL: {
                         babylonLight = new DirectionalLight(name, Vector3.Forward(), this._loader._babylonScene);
@@ -78,7 +78,7 @@ module BABYLON.GLTF2.Extensions {
                         break;
                     }
                     default: {
-                        throw new Error(`${context}: Invalid light type (${light.type})`);
+                        throw new Error(`${extensionContext}: Invalid light type (${light.type})`);
                     }
                 }
 

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

@@ -17,7 +17,7 @@ module BABYLON.GLTF2.Extensions {
         public readonly name = NAME;
 
         protected _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
-            return this._loadExtensionAsync<IKHRMaterialsPbrSpecularGlossiness>(context, material, (context, extension) => {
+            return this._loadExtensionAsync<IKHRMaterialsPbrSpecularGlossiness>(context, material, (extensionContext, extension) => {
                 material._babylonData = material._babylonData || {};
                 let babylonData = material._babylonData[babylonDrawMode];
                 if (!babylonData) {
@@ -27,7 +27,7 @@ module BABYLON.GLTF2.Extensions {
                     const babylonMaterial = this._loader._createMaterial(PBRMaterial, name, babylonDrawMode);
 
                     promises.push(this._loader._loadMaterialBasePropertiesAsync(context, material, babylonMaterial));
-                    promises.push(this._loadSpecularGlossinessPropertiesAsync(context, material, extension, babylonMaterial));
+                    promises.push(this._loadSpecularGlossinessPropertiesAsync(extensionContext, material, extension, babylonMaterial));
 
                     this._loader.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
 

+ 76 - 0
loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts

@@ -0,0 +1,76 @@
+/// <reference path="../../../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GLTF2.Extensions {
+    // https://github.com/donmccurdy/glTF/tree/feat-khr-materials-cmnConstant/extensions/2.0/Khronos/KHR_materials_unlit
+
+    const NAME = "KHR_materials_unlit";
+
+    export class KHR_materials_unlit extends GLTFLoaderExtension {
+        public readonly name = NAME;
+
+        protected _loadMaterialAsync(context: string, material: ILoaderMaterial, babylonMesh: Mesh, babylonDrawMode: number, assign: (babylonMaterial: Material) => void): Nullable<Promise<void>> {
+            return this._loadExtensionAsync<{}>(context, material, () => {
+                material._babylonData = material._babylonData || {};
+                let babylonData = material._babylonData[babylonDrawMode];
+                if (!babylonData) {
+                    const name = material.name || `materialUnlit_${material._index}`;
+                    const babylonMaterial = this._loader._createMaterial(PBRMaterial, name, babylonDrawMode);
+                    babylonMaterial.unlit = true;
+
+                    const promise = this._loadUnlitPropertiesAsync(context, material, babylonMaterial);
+
+                    this._loader.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
+
+                    babylonData = {
+                        material: babylonMaterial,
+                        meshes: [],
+                        loaded: promise
+                    };
+
+                    material._babylonData[babylonDrawMode] = babylonData;
+                }
+
+                babylonData.meshes.push(babylonMesh);
+
+                assign(babylonData.material);
+                return babylonData.loaded;
+            });
+        }
+
+        private _loadUnlitPropertiesAsync(context: string, material: ILoaderMaterial, babylonMaterial: PBRMaterial): Promise<void> {
+            const promises = new Array<Promise<void>>();
+
+            // Ensure metallic workflow
+            babylonMaterial.metallic = 1;
+            babylonMaterial.roughness = 1;
+
+            const properties = material.pbrMetallicRoughness;
+            if (properties) {
+                if (properties.baseColorFactor) {
+                    babylonMaterial.albedoColor = Color3.FromArray(properties.baseColorFactor);
+                    babylonMaterial.alpha = properties.baseColorFactor[3];
+                }
+                else {
+                    babylonMaterial.albedoColor = Color3.White();
+                }
+
+                if (properties.baseColorTexture) {
+                    promises.push(this._loader._loadTextureAsync(`${context}/baseColorTexture`, properties.baseColorTexture, texture => {
+                        babylonMaterial.albedoTexture = texture;
+                    }));
+                }
+            }
+
+            if (material.doubleSided) {
+                babylonMaterial.backFaceCulling = false;
+                babylonMaterial.twoSidedLighting = true;
+            }
+
+            this._loader._loadMaterialAlphaProperties(context, material, babylonMaterial);
+
+            return Promise.all(promises).then(() => {});
+        }
+    }
+
+    GLTFLoader._Register(NAME, loader => new KHR_materials_unlit(loader));
+}

+ 4 - 4
loaders/src/glTF/2.0/Extensions/MSFT_lod.ts

@@ -24,10 +24,10 @@ module BABYLON.GLTF2.Extensions {
         private _loadMaterialSignals: { [materialIndex: number]: Deferred<void> } = {};
 
         protected _loadNodeAsync(context: string, node: ILoaderNode): Nullable<Promise<void>> {
-            return this._loadExtensionAsync<IMSFTLOD>(context, node, (context, extension) => {
+            return this._loadExtensionAsync<IMSFTLOD>(context, node, (extensionContext, extension) => {
                 let firstPromise: Promise<void>;
 
-                const nodeLODs = this._getLODs(context, node, this._loader._gltf.nodes, extension.ids);
+                const nodeLODs = this._getLODs(extensionContext, node, this._loader._gltf.nodes, extension.ids);
                 for (let indexLOD = 0; indexLOD < nodeLODs.length; indexLOD++) {
                     const nodeLOD = nodeLODs[indexLOD];
 
@@ -77,10 +77,10 @@ module BABYLON.GLTF2.Extensions {
                 return null;
             }
 
-            return this._loadExtensionAsync<IMSFTLOD>(context, material, (context, extension) => {
+            return this._loadExtensionAsync<IMSFTLOD>(context, material, (extensionContext, extension) => {
                 let firstPromise: Promise<void>;
 
-                const materialLODs = this._getLODs(context, material, this._loader._gltf.materials, extension.ids);
+                const materialLODs = this._getLODs(extensionContext, material, this._loader._gltf.materials, extension.ids);
                 for (let indexLOD = 0; indexLOD < materialLODs.length; indexLOD++) {
                     const materialLOD = materialLODs[indexLOD];
 

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

@@ -35,7 +35,7 @@ module BABYLON.GLTF2 {
         // #endregion
 
         /** Helper method called by a loader extension to load an glTF extension. */
-        protected _loadExtensionAsync<TProperty, TResult = void>(context: string, property: IProperty, actionAsync: (context: string, extension: TProperty) => Promise<TResult>): Nullable<Promise<TResult>> {
+        protected _loadExtensionAsync<TProperty, TResult = void>(context: string, property: IProperty, actionAsync: (extensionContext: string, extension: TProperty) => Promise<TResult>): Nullable<Promise<TResult>> {
             if (!property.extensions) {
                 return null;
             }